#include "sql_parser.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

// Forward declarations
static void detect_subquery_correlation(expression_t* subquery_expr, statement_t* subquery_stmt);

// Keyword mapping table
static struct {
    const char* keyword;
    token_type_t token_type;
} keyword_table[] = {
    {"SELECT", TOKEN_SELECT},
    {"FROM", TOKEN_FROM},
    {"WHERE", TOKEN_WHERE},
    {"INSERT", TOKEN_INSERT},
    {"INTO", TOKEN_INTO},
    {"VALUES", TOKEN_VALUES},
    {"UPDATE", TOKEN_UPDATE},
    {"SET", TOKEN_SET},
    {"DELETE", TOKEN_DELETE},
    {"CREATE", TOKEN_CREATE},
    {"TABLE", TOKEN_TABLE},
    {"VIEW", TOKEN_VIEW},
    {"DROP", TOKEN_DROP},
    {"ALTER", TOKEN_ALTER},
    {"GRANT", TOKEN_GRANT},
    {"REVOKE", TOKEN_REVOKE},
    {"USER", TOKEN_USER},
    {"AND", TOKEN_AND},
    {"OR", TOKEN_OR},
    {"NOT", TOKEN_NOT},
    {"IN", TOKEN_IN},
    {"IF", TOKEN_IF},
    {"LIKE", TOKEN_LIKE},
    {"ORDER", TOKEN_ORDER},
    {"BY", TOKEN_BY},
    {"GROUP", TOKEN_GROUP},
    {"COUNT", TOKEN_COUNT},
    {"SUM", TOKEN_SUM},
    {"AVG", TOKEN_AVG},
    {"MIN", TOKEN_MIN},
    {"MAX", TOKEN_MAX},
    {"HAVING", TOKEN_HAVING},
    {"LIMIT", TOKEN_LIMIT},
    {"OFFSET", TOKEN_OFFSET},
    {"JOIN", TOKEN_JOIN},
    {"LEFT", TOKEN_LEFT},
    {"RIGHT", TOKEN_RIGHT},
    {"INNER", TOKEN_INNER},
    {"OUTER", TOKEN_OUTER},
    {"ON", TOKEN_ON},
    {"AS", TOKEN_AS},
    {"ASC", TOKEN_ASC},
    {"DESC", TOKEN_DESC},
    {"DISTINCT", TOKEN_DISTINCT},
    {"ALL", TOKEN_ALL},
    {"UNION", TOKEN_UNION},
    {"INTERSECT", TOKEN_INTERSECT},
    {"EXCEPT", TOKEN_EXCEPT},
    {"EXISTS", TOKEN_EXISTS},
    {"BETWEEN", TOKEN_BETWEEN},
    {"IS", TOKEN_IS},
    {"NULL", TOKEN_NULL},
    {"TRUE", TOKEN_TRUE},
    {"FALSE", TOKEN_FALSE},
    {"PRIMARY", TOKEN_PRIMARY},
    {"KEY", TOKEN_KEY},
    {"FOREIGN", TOKEN_FOREIGN},
    {"REFERENCES", TOKEN_REFERENCES},
    {"UNIQUE", TOKEN_UNIQUE},
    {"INDEX", TOKEN_INDEX},
    {"DEFAULT", TOKEN_DEFAULT},
    {"AUTO_INCREMENT", TOKEN_AUTO_INCREMENT},
    {"PARTITION", TOKEN_PARTITION},
    {"RANGE", TOKEN_RANGE},
    {"HASH", TOKEN_HASH},
    {"LESS", TOKEN_LESS},
    {"THAN", TOKEN_THAN},
    {"ENGINE", TOKEN_ENGINE},
    {"ENCRYPTED", TOKEN_ENCRYPTED},
    {"YES", TOKEN_YES},
    {"IDENTIFIED", TOKEN_IDENTIFIED},
    {"PASSWORD", TOKEN_PASSWORD},
    {"START", TOKEN_START},
    {"TRANSACTION", TOKEN_TRANSACTION},
    {"COMMIT", TOKEN_COMMIT},
    {"ROLLBACK", TOKEN_ROLLBACK},
    {"ANALYZE", TOKEN_ANALYZE},
    {"DESCRIBE", TOKEN_DESCRIBE},
    {"SHOW", TOKEN_SHOW},
    {"USE", TOKEN_USE},
    {"COLUMNS", TOKEN_COLUMNS},
    {"STATUS", TOKEN_STATUS},
    {"DATABASE", TOKEN_DATABASE},
    {"TRIGGER", TOKEN_TRIGGER},
    {"BEFORE", TOKEN_BEFORE},
    {"AFTER", TOKEN_AFTER},
    {"INSTEAD", TOKEN_INSTEAD},
    {"WHEN", TOKEN_WHEN},
    {"FOR", TOKEN_FOR},
    {"EACH", TOKEN_EACH},
    {"ROW", TOKEN_ROW},
    {"TINYINT", TOKEN_TINYINT},
    {"INT", TOKEN_INT},
    {"BIGINT", TOKEN_BIGINT},
    {"FLOAT", TOKEN_FLOAT},
    {"DOUBLE", TOKEN_DOUBLE},
    {"CHAR", TOKEN_CHAR},
    {"VARCHAR", TOKEN_VARCHAR},
    {"TEXT", TOKEN_TEXT},
    {"JSON", TOKEN_JSON},
    {"DATE", TOKEN_DATE},
    {"DATETIME", TOKEN_DATETIME},
    {"TIMESTAMP", TOKEN_TIMESTAMP},
    {NULL, TOKEN_INVALID}
};

// Helper functions
bool is_keyword(const char* word) {
    for (int i = 0; keyword_table[i].keyword != NULL; i++) {
        if (strcasecmp(word, keyword_table[i].keyword) == 0) {
            return true;
        }
    }
    return false;
}

token_type_t keyword_to_token_type(const char* keyword) {
    for (int i = 0; keyword_table[i].keyword != NULL; i++) {
        if (strcasecmp(keyword, keyword_table[i].keyword) == 0) {
            return keyword_table[i].token_type;
        }
    }
    return TOKEN_IDENTIFIER;
}

bool is_whitespace(char c) {
    return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}

bool is_alpha(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}

bool is_digit(char c) {
    return c >= '0' && c <= '9';
}

bool is_alnum(char c) {
    return is_alpha(c) || is_digit(c);
}

// Token functions
token_t* token_create(token_type_t type, const char* value, uint32_t length) {
    token_t* token = calloc(1, sizeof(token_t));
    if (!token) return NULL;
    
    token->type = type;
    if (value && length > 0) {
        token->value = malloc(length + 1);
        if (token->value) {
            memcpy(token->value, value, length);
            token->value[length] = '\0';
            token->length = length;
        }
    }
    return token;
}

void token_destroy(token_t* token) {
    if (!token) return;
    if (token->value) {
        free(token->value);
    }
    free(token);
}

bool token_match(token_t* token, token_type_t type) {
    return token && token->type == type;
}

bool token_match_keyword(token_t* token, const char* keyword) {
    return token && token->type == TOKEN_KEYWORD && 
           token->value && strcasecmp(token->value, keyword) == 0;
}

// Lexer implementation
lexer_t* lexer_create(const char* input) {
    if (!input) return NULL;
    
    lexer_t* lexer = calloc(1, sizeof(lexer_t));
    if (!lexer) return NULL;
    
    lexer->input = input;
    lexer->length = strlen(input);
    lexer->position = 0;
    lexer->line = 1;
    lexer->column = 1;
    
    return lexer;
}

void lexer_destroy(lexer_t* lexer) {
    if (!lexer) return;
    if (lexer->error_message) {
        free(lexer->error_message);
    }
    free(lexer);
}

static void lexer_skip_whitespace(lexer_t* lexer) {
    while (lexer->position < lexer->length && 
           is_whitespace(lexer->input[lexer->position])) {
        if (lexer->input[lexer->position] == '\n') {
            lexer->line++;
            lexer->column = 1;
        } else {
            lexer->column++;
        }
        lexer->position++;
    }
}

static void lexer_skip_comment(lexer_t* lexer) {
    if (lexer->position + 1 < lexer->length && 
        lexer->input[lexer->position] == '-' && 
        lexer->input[lexer->position + 1] == '-') {
        // Single line comment
        while (lexer->position < lexer->length && 
               lexer->input[lexer->position] != '\n') {
            lexer->position++;
            lexer->column++;
        }
    } else if (lexer->position + 1 < lexer->length && 
               lexer->input[lexer->position] == '/' && 
               lexer->input[lexer->position + 1] == '*') {
        // Multi-line comment
        lexer->position += 2;
        lexer->column += 2;
        
        while (lexer->position + 1 < lexer->length) {
            if (lexer->input[lexer->position] == '*' && 
                lexer->input[lexer->position + 1] == '/') {
                lexer->position += 2;
                lexer->column += 2;
                break;
            }
            if (lexer->input[lexer->position] == '\n') {
                lexer->line++;
                lexer->column = 1;
            } else {
                lexer->column++;
            }
            lexer->position++;
        }
    }
}

static token_t* lexer_read_string(lexer_t* lexer) {
    char quote = lexer->input[lexer->position];
    uint32_t start = ++lexer->position;
    lexer->column++;
    
    while (lexer->position < lexer->length && 
           lexer->input[lexer->position] != quote) {
        if (lexer->input[lexer->position] == '\\' && 
            lexer->position + 1 < lexer->length) {
            lexer->position += 2;  // Skip escaped character
            lexer->column += 2;
        } else {
            if (lexer->input[lexer->position] == '\n') {
                lexer->line++;
                lexer->column = 1;
            } else {
                lexer->column++;
            }
            lexer->position++;
        }
    }
    
    if (lexer->position >= lexer->length) {
        lexer->error_message = strdup("Unterminated string literal");
        return NULL;
    }
    
    uint32_t length = lexer->position - start;
    token_t* token = token_create(TOKEN_STRING, lexer->input + start, length);
    
    lexer->position++;  // Skip closing quote
    lexer->column++;
    
    return token;
}

static token_t* lexer_read_number(lexer_t* lexer) {
    uint32_t start = lexer->position;
    
    while (lexer->position < lexer->length && 
           is_digit(lexer->input[lexer->position])) {
        lexer->position++;
        lexer->column++;
    }
    
    // Handle decimal point
    if (lexer->position < lexer->length && 
        lexer->input[lexer->position] == '.') {
        lexer->position++;
        lexer->column++;
        
        while (lexer->position < lexer->length && 
               is_digit(lexer->input[lexer->position])) {
            lexer->position++;
            lexer->column++;
        }
    }
    
    uint32_t length = lexer->position - start;
    return token_create(TOKEN_NUMBER, lexer->input + start, length);
}

static token_t* lexer_read_identifier(lexer_t* lexer) {
    uint32_t start = lexer->position;
    
    while (lexer->position < lexer->length && 
           is_alnum(lexer->input[lexer->position])) {
        lexer->position++;
        lexer->column++;
    }
    
    uint32_t length = lexer->position - start;
    token_t* token = token_create(TOKEN_IDENTIFIER, lexer->input + start, length);
    
    // Check if it's a keyword
    if (token && token->value && is_keyword(token->value)) {
        token->type = keyword_to_token_type(token->value);
    }
    
    return token;
}

token_t* lexer_next_token(lexer_t* lexer) {
    if (!lexer) return NULL;
    
    // Note: Don't clean up previous token here, let the caller manage token memory
    
    while (lexer->position < lexer->length) {
        lexer_skip_whitespace(lexer);
        
        if (lexer->position >= lexer->length) {
            break;
        }
        
        // Skip comments
        if ((lexer->input[lexer->position] == '-' && 
             lexer->position + 1 < lexer->length && 
             lexer->input[lexer->position + 1] == '-') ||
            (lexer->input[lexer->position] == '/' && 
             lexer->position + 1 < lexer->length && 
             lexer->input[lexer->position + 1] == '*')) {
            lexer_skip_comment(lexer);
            continue;
        }
        
        char c = lexer->input[lexer->position];
        
        // String literals
        if (c == '\'' || c == '"' || c == '`') {
            return lexer_read_string(lexer);
        }
        
        // Numbers
        if (is_digit(c)) {
            return lexer_read_number(lexer);
        }
        
        // Identifiers and keywords
        if (is_alpha(c)) {
            return lexer_read_identifier(lexer);
        }
        
        // Operators and punctuation
        token_type_t token_type = TOKEN_INVALID;
        uint32_t token_length = 1;
        
        switch (c) {
            case '=': token_type = TOKEN_EQUAL; break;
            case '<':
                if (lexer->position + 1 < lexer->length) {
                    if (lexer->input[lexer->position + 1] == '=') {
                        token_type = TOKEN_LESS_EQUAL;
                        token_length = 2;
                    } else if (lexer->input[lexer->position + 1] == '>') {
                        token_type = TOKEN_NOT_EQUAL;
                        token_length = 2;
                    } else {
                        token_type = TOKEN_LESS_THAN;
                    }
                } else {
                    token_type = TOKEN_LESS_THAN;
                }
                break;
            case '>':
                if (lexer->position + 1 < lexer->length && 
                    lexer->input[lexer->position + 1] == '=') {
                    token_type = TOKEN_GREATER_EQUAL;
                    token_length = 2;
                } else {
                    token_type = TOKEN_GREATER_THAN;
                }
                break;
            case '!':
                if (lexer->position + 1 < lexer->length && 
                    lexer->input[lexer->position + 1] == '=') {
                    token_type = TOKEN_NOT_EQUAL;
                    token_length = 2;
                }
                break;
            case '+': token_type = TOKEN_PLUS; break;
            case '-': token_type = TOKEN_MINUS; break;
            case '*': token_type = TOKEN_MULTIPLY; break;
            case '/': token_type = TOKEN_DIVIDE; break;
            case '%': token_type = TOKEN_MODULO; break;
            case ';': token_type = TOKEN_SEMICOLON; break;
            case ',': token_type = TOKEN_COMMA; break;
            case '.': token_type = TOKEN_DOT; break;
            case '(': token_type = TOKEN_LPAREN; break;
            case ')': token_type = TOKEN_RPAREN; break;
            case '{': token_type = TOKEN_LBRACE; break;
            case '}': token_type = TOKEN_RBRACE; break;
            case '[': token_type = TOKEN_LBRACKET; break;
            case ']': token_type = TOKEN_RBRACKET; break;
            case '?': token_type = TOKEN_QUESTION; break;
            case '@': token_type = TOKEN_AT; break;
            case '$': token_type = TOKEN_DOLLAR; break;
        }
        
        if (token_type != TOKEN_INVALID) {
            token_t* token = token_create(token_type, 
                                        lexer->input + lexer->position, 
                                        token_length);
            lexer->position += token_length;
            lexer->column += token_length;
            return token;
        }
        
        // Unknown character
        char error_msg[256];
        snprintf(error_msg, sizeof(error_msg), 
                "Unexpected character '%c' at line %d, column %d", 
                c, lexer->line, lexer->column);
        lexer->error_message = strdup(error_msg);
        return NULL;
    }
    
    // End of input
    return token_create(TOKEN_EOF, NULL, 0);
}

token_t* lexer_peek_token(lexer_t* lexer) {
    // Save current state
    uint32_t saved_position = lexer->position;
    uint32_t saved_line = lexer->line;
    uint32_t saved_column = lexer->column;
    
    // Get next token
    token_t* next_token = lexer_next_token(lexer);
    
    // Create a copy of the token
    token_t* peek_token = NULL;
    if (next_token) {
        peek_token = token_create(next_token->type, next_token->value, next_token->length);
        peek_token->line = next_token->line;
        peek_token->column = next_token->column;
        token_destroy(next_token);  // Clean up the temporary token
    }
    
    // Restore state
    lexer->position = saved_position;
    lexer->line = saved_line;
    lexer->column = saved_column;
    
    return peek_token;
}

// Parser implementation
parser_t* parser_create(const char* sql) {
    if (!sql) return NULL;
    
    parser_t* parser = calloc(1, sizeof(parser_t));
    if (!parser) return NULL;
    
    parser->lexer = lexer_create(sql);
    if (!parser->lexer) {
        free(parser);
        return NULL;
    }
    
    // Get first token
    parser->current_token = lexer_next_token(parser->lexer);
    
    return parser;
}

void parser_destroy(parser_t* parser) {
    if (!parser) return;
    
    if (parser->lexer) {
        lexer_destroy(parser->lexer);
    }
    if (parser->current_token) {
        token_destroy(parser->current_token);
    }
    if (parser->error_message) {
        free(parser->error_message);
    }
    free(parser);
}

static bool parser_consume_token(parser_t* parser, token_type_t expected) {
    if (!parser->current_token || parser->current_token->type != expected) {
        return false;
    }
    
    token_destroy(parser->current_token);
    parser->current_token = lexer_next_token(parser->lexer);
    return true;
}

static bool parser_match_token(parser_t* parser, token_type_t type) {
    return parser->current_token && parser->current_token->type == type;
}

void parser_set_error(parser_t* parser, const char* message) {
    if (!parser || !message) return;
    
    if (parser->error_message) {
        free(parser->error_message);
    }
    
    char full_message[512];
    if (parser->current_token) {
        snprintf(full_message, sizeof(full_message), 
                "%s at line %d, column %d", 
                message, parser->current_token->line, parser->current_token->column);
    } else {
        snprintf(full_message, sizeof(full_message), "%s", message);
    }
    
    parser->error_message = strdup(full_message);
    if (parser->current_token) {
        parser->error_line = parser->current_token->line;
        parser->error_column = parser->current_token->column;
    }
}

bool parser_has_error(parser_t* parser) {
    return parser && parser->error_message != NULL;
}

const char* parser_get_error(parser_t* parser) {
    return parser ? parser->error_message : "Invalid parser";
}

// Expression parsing
expression_t* parser_parse_primary_expression(parser_t* parser) {
    if (!parser->current_token) {
        parser_set_error(parser, "Unexpected end of input");
        return NULL;
    }
    
    expression_t* expr = calloc(1, sizeof(expression_t));
    if (!expr) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    switch (parser->current_token->type) {
        case TOKEN_NUMBER:
            expr->type = EXPR_LITERAL;
            expr->data.literal.value = strdup(parser->current_token->value);
            expr->data.literal.length = parser->current_token->length;
            parser_consume_token(parser, TOKEN_NUMBER);
            break;
            
        case TOKEN_STRING:
            expr->type = EXPR_LITERAL;
            expr->data.literal.value = strdup(parser->current_token->value);
            expr->data.literal.length = parser->current_token->length;
            parser_consume_token(parser, TOKEN_STRING);
            break;
            
        case TOKEN_COUNT:
        case TOKEN_SUM:
        case TOKEN_AVG:
        case TOKEN_MIN:
        case TOKEN_MAX:
            // Parse aggregate function
            expr->type = EXPR_FUNCTION_CALL;
            expr->data.function_call.function_name = strdup(parser->current_token->value);
            parser_consume_token(parser, parser->current_token->type);
            
            if (!parser_consume_token(parser, TOKEN_LPAREN)) {
                parser_set_error(parser, "Expected '(' after function name");
                expression_destroy(expr);
                return NULL;
            }
            
            // Parse function arguments
            expr->data.function_call.arg_count = 0;
            expr->data.function_call.args = NULL;
            
            if (!parser_match_token(parser, TOKEN_RPAREN)) {
                // Parse first argument
                uint32_t capacity = 4;
                expr->data.function_call.args = malloc(capacity * sizeof(expression_t*));
                if (!expr->data.function_call.args) {
                    parser_set_error(parser, "Out of memory");
                    expression_destroy(expr);
                    return NULL;
                }
                
                expression_t* arg = parser_parse_expression(parser);
                if (!arg) {
                    expression_destroy(expr);
                    return NULL;
                }
                
                expr->data.function_call.args[0] = arg;
                expr->data.function_call.arg_count = 1;
                
                // Parse additional arguments
                while (parser_match_token(parser, TOKEN_COMMA)) {
                    parser_consume_token(parser, TOKEN_COMMA);
                    
                    if (expr->data.function_call.arg_count >= capacity) {
                        capacity *= 2;
                        expression_t** new_args = realloc(expr->data.function_call.args, 
                                                         capacity * sizeof(expression_t*));
                        if (!new_args) {
                            parser_set_error(parser, "Out of memory");
                            expression_destroy(expr);
                            return NULL;
                        }
                        expr->data.function_call.args = new_args;
                    }
                    
                    arg = parser_parse_expression(parser);
                    if (!arg) {
                        expression_destroy(expr);
                        return NULL;
                    }
                    
                    expr->data.function_call.args[expr->data.function_call.arg_count++] = arg;
                }
            }
            
            if (!parser_consume_token(parser, TOKEN_RPAREN)) {
                parser_set_error(parser, "Expected ')' after function arguments");
                expression_destroy(expr);
                return NULL;
            }
            break;
            
        case TOKEN_EXISTS:
            // Parse EXISTS subquery
            expr->type = EXPR_FUNCTION_CALL;
            expr->data.function_call.function_name = strdup("EXISTS");
            parser_consume_token(parser, TOKEN_EXISTS);
            
            if (!parser_consume_token(parser, TOKEN_LPAREN)) {
                parser_set_error(parser, "Expected '(' after EXISTS");
                expression_destroy(expr);
                return NULL;
            }
            
            // Ensure this is a SELECT subquery
            if (!parser_match_token(parser, TOKEN_SELECT)) {
                parser_set_error(parser, "Expected SELECT after EXISTS (");
                expression_destroy(expr);
                return NULL;
            }
            
            // Parse the subquery
            statement_t* exists_subquery = parser_parse_select(parser);
            if (!exists_subquery) {
                expression_destroy(expr);
                return NULL;
            }
            
            // Create subquery expression as argument
            expression_t* subquery_expr = calloc(1, sizeof(expression_t));
            if (!subquery_expr) {
                parser_set_error(parser, "Out of memory");
                statement_destroy(exists_subquery);
                expression_destroy(expr);
                return NULL;
            }
            
            subquery_expr->type = EXPR_SUBQUERY;
            subquery_expr->data.subquery.query = exists_subquery;
            // Detect correlation in the subquery
            detect_subquery_correlation(subquery_expr, exists_subquery);
            
            // Set subquery as argument to EXISTS function
            expr->data.function_call.args = malloc(sizeof(expression_t*));
            if (!expr->data.function_call.args) {
                parser_set_error(parser, "Out of memory");
                expression_destroy(subquery_expr);
                expression_destroy(expr);
                return NULL;
            }
            
            expr->data.function_call.args[0] = subquery_expr;
            expr->data.function_call.arg_count = 1;
            
            if (!parser_consume_token(parser, TOKEN_RPAREN)) {
                parser_set_error(parser, "Expected ')' after EXISTS subquery");
                expression_destroy(expr);
                return NULL;
            }
            break;
            
        case TOKEN_IDENTIFIER:
            // Could be a column reference or a function call
            {
                char* identifier = strdup(parser->current_token->value);
                parser_consume_token(parser, TOKEN_IDENTIFIER);
                
                if (parser_match_token(parser, TOKEN_LPAREN)) {
                    // Function call
                    expr->type = EXPR_FUNCTION_CALL;
                    expr->data.function_call.function_name = identifier;
                    parser_consume_token(parser, TOKEN_LPAREN);
                    
                    // Parse function arguments (same logic as aggregate functions)
                    expr->data.function_call.arg_count = 0;
                    expr->data.function_call.args = NULL;
                    
                    if (!parser_match_token(parser, TOKEN_RPAREN)) {
                        uint32_t capacity = 4;
                        expr->data.function_call.args = malloc(capacity * sizeof(expression_t*));
                        if (!expr->data.function_call.args) {
                            parser_set_error(parser, "Out of memory");
                            free(identifier);
                            expression_destroy(expr);
                            return NULL;
                        }
                        
                        expression_t* arg = parser_parse_expression(parser);
                        if (!arg) {
                            free(identifier);
                            expression_destroy(expr);
                            return NULL;
                        }
                        
                        expr->data.function_call.args[0] = arg;
                        expr->data.function_call.arg_count = 1;
                        
                        while (parser_match_token(parser, TOKEN_COMMA)) {
                            parser_consume_token(parser, TOKEN_COMMA);
                            
                            if (expr->data.function_call.arg_count >= capacity) {
                                capacity *= 2;
                                expression_t** new_args = realloc(expr->data.function_call.args, 
                                                                 capacity * sizeof(expression_t*));
                                if (!new_args) {
                                    parser_set_error(parser, "Out of memory");
                                    free(identifier);
                                    expression_destroy(expr);
                                    return NULL;
                                }
                                expr->data.function_call.args = new_args;
                            }
                            
                            arg = parser_parse_expression(parser);
                            if (!arg) {
                                free(identifier);
                                expression_destroy(expr);
                                return NULL;
                            }
                            
                            expr->data.function_call.args[expr->data.function_call.arg_count++] = arg;
                        }
                    }
                    
                    if (!parser_consume_token(parser, TOKEN_RPAREN)) {
                        parser_set_error(parser, "Expected ')' after function arguments");
                        free(identifier);
                        expression_destroy(expr);
                        return NULL;
                    }
                } else {
                    // Column reference
                    expr->type = EXPR_COLUMN;
                    expr->data.column.column_name = identifier;
                    
                    // Check for table.column syntax
                    if (parser_match_token(parser, TOKEN_DOT)) {
                        parser_consume_token(parser, TOKEN_DOT);
                        if (parser_match_token(parser, TOKEN_IDENTIFIER)) {
                            expr->data.column.table_name = expr->data.column.column_name;
                            expr->data.column.column_name = strdup(parser->current_token->value);
                            parser_consume_token(parser, TOKEN_IDENTIFIER);
                        } else {
                            parser_set_error(parser, "Expected column name after '.'");
                            expression_destroy(expr);
                            return NULL;
                        }
                    }
                }
            }
            break;
            
        case TOKEN_MULTIPLY:
            expr->type = EXPR_STAR;
            parser_consume_token(parser, TOKEN_MULTIPLY);
            break;
            
        case TOKEN_LPAREN: {
            // Look ahead to see if this is a subquery
            token_t* peek_token = lexer_peek_token(parser->lexer);
            if (peek_token && peek_token->type == TOKEN_SELECT) {
                // This is a subquery
                parser_consume_token(parser, TOKEN_LPAREN);
                
                // Parse the SELECT statement
                statement_t* subquery_stmt = parser_parse_select(parser);
                if (!subquery_stmt) {
                    token_destroy(peek_token);
                    expression_destroy(expr);
                    return NULL;
                }
                
                // Create subquery expression
                expr->type = EXPR_SUBQUERY;
                expr->data.subquery.query = subquery_stmt;
                // Detect correlation in the subquery
                detect_subquery_correlation(expr, subquery_stmt);
                
                if (!parser_consume_token(parser, TOKEN_RPAREN)) {
                    parser_set_error(parser, "Expected ')' after subquery");
                    token_destroy(peek_token);
                    expression_destroy(expr);
                    return NULL;
                }
                
                token_destroy(peek_token);
            } else {
                // Regular parenthesized expression
                parser_consume_token(parser, TOKEN_LPAREN);
                expression_destroy(expr);
                expr = parser_parse_expression(parser);
                if (!expr) {
                    if (peek_token) token_destroy(peek_token);
                    return NULL;
                }
                
                if (!parser_consume_token(parser, TOKEN_RPAREN)) {
                    parser_set_error(parser, "Expected ')' after expression");
                    expression_destroy(expr);
                    if (peek_token) token_destroy(peek_token);
                    return NULL;
                }
                
                if (peek_token) token_destroy(peek_token);
            }
            break;
        }
            
        default:
            parser_set_error(parser, "Expected expression");
            free(expr);
            return NULL;
    }
    
    return expr;
}

expression_t* parser_parse_expression(parser_t* parser) {
    return parser_parse_or_expression(parser);
}

expression_t* parser_parse_or_expression(parser_t* parser) {
    expression_t* left = parser_parse_and_expression(parser);
    if (!left) return NULL;
    
    while (parser_match_token(parser, TOKEN_OR)) {
        token_type_t op = parser->current_token->type;
        parser_consume_token(parser, TOKEN_OR);
        
        expression_t* right = parser_parse_and_expression(parser);
        if (!right) {
            expression_destroy(left);
            return NULL;
        }
        
        expression_t* binary_expr = calloc(1, sizeof(expression_t));
        if (!binary_expr) {
            expression_destroy(left);
            expression_destroy(right);
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        binary_expr->type = EXPR_BINARY_OP;
        binary_expr->data.binary_op.operator = op;
        binary_expr->data.binary_op.left = left;
        binary_expr->data.binary_op.right = right;
        
        left = binary_expr;
    }
    
    return left;
}

expression_t* parser_parse_and_expression(parser_t* parser) {
    expression_t* left = parser_parse_equality_expression(parser);
    if (!left) return NULL;
    
    while (parser_match_token(parser, TOKEN_AND)) {
        token_type_t op = parser->current_token->type;
        parser_consume_token(parser, TOKEN_AND);
        
        expression_t* right = parser_parse_equality_expression(parser);
        if (!right) {
            expression_destroy(left);
            return NULL;
        }
        
        expression_t* binary_expr = calloc(1, sizeof(expression_t));
        if (!binary_expr) {
            expression_destroy(left);
            expression_destroy(right);
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        binary_expr->type = EXPR_BINARY_OP;
        binary_expr->data.binary_op.operator = op;
        binary_expr->data.binary_op.left = left;
        binary_expr->data.binary_op.right = right;
        
        left = binary_expr;
    }
    
    return left;
}

expression_t* parser_parse_equality_expression(parser_t* parser) {
    expression_t* left = parser_parse_relational_expression(parser);
    if (!left) return NULL;
    
    while (parser_match_token(parser, TOKEN_EQUAL) || 
           parser_match_token(parser, TOKEN_NOT_EQUAL)) {
        token_type_t op = parser->current_token->type;
        parser_consume_token(parser, op);
        
        expression_t* right = parser_parse_relational_expression(parser);
        if (!right) {
            expression_destroy(left);
            return NULL;
        }
        
        expression_t* binary_expr = calloc(1, sizeof(expression_t));
        if (!binary_expr) {
            expression_destroy(left);
            expression_destroy(right);
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        binary_expr->type = EXPR_BINARY_OP;
        binary_expr->data.binary_op.operator = op;
        binary_expr->data.binary_op.left = left;
        binary_expr->data.binary_op.right = right;
        
        left = binary_expr;
    }
    
    return left;
}

expression_t* parser_parse_relational_expression(parser_t* parser) {
    expression_t* left = parser_parse_additive_expression(parser);
    if (!left) return NULL;
    
    while (parser_match_token(parser, TOKEN_LESS_THAN) || 
           parser_match_token(parser, TOKEN_LESS_EQUAL) ||
           parser_match_token(parser, TOKEN_GREATER_THAN) || 
           parser_match_token(parser, TOKEN_GREATER_EQUAL)) {
        token_type_t op = parser->current_token->type;
        parser_consume_token(parser, op);
        
        expression_t* right = parser_parse_additive_expression(parser);
        if (!right) {
            expression_destroy(left);
            return NULL;
        }
        
        expression_t* binary_expr = calloc(1, sizeof(expression_t));
        if (!binary_expr) {
            expression_destroy(left);
            expression_destroy(right);
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        binary_expr->type = EXPR_BINARY_OP;
        binary_expr->data.binary_op.operator = op;
        binary_expr->data.binary_op.left = left;
        binary_expr->data.binary_op.right = right;
        
        left = binary_expr;
    }
    
    return left;
}

expression_t* parser_parse_additive_expression(parser_t* parser) {
    expression_t* left = parser_parse_multiplicative_expression(parser);
    if (!left) return NULL;
    
    while (parser_match_token(parser, TOKEN_PLUS) || 
           parser_match_token(parser, TOKEN_MINUS)) {
        token_type_t op = parser->current_token->type;
        parser_consume_token(parser, op);
        
        expression_t* right = parser_parse_multiplicative_expression(parser);
        if (!right) {
            expression_destroy(left);
            return NULL;
        }
        
        expression_t* binary_expr = calloc(1, sizeof(expression_t));
        if (!binary_expr) {
            expression_destroy(left);
            expression_destroy(right);
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        binary_expr->type = EXPR_BINARY_OP;
        binary_expr->data.binary_op.operator = op;
        binary_expr->data.binary_op.left = left;
        binary_expr->data.binary_op.right = right;
        
        left = binary_expr;
    }
    
    return left;
}

expression_t* parser_parse_multiplicative_expression(parser_t* parser) {
    expression_t* left = parser_parse_unary_expression(parser);
    if (!left) return NULL;
    
    while (parser_match_token(parser, TOKEN_MULTIPLY) || 
           parser_match_token(parser, TOKEN_DIVIDE) ||
           parser_match_token(parser, TOKEN_MODULO)) {
        token_type_t op = parser->current_token->type;
        parser_consume_token(parser, op);
        
        expression_t* right = parser_parse_unary_expression(parser);
        if (!right) {
            expression_destroy(left);
            return NULL;
        }
        
        expression_t* binary_expr = calloc(1, sizeof(expression_t));
        if (!binary_expr) {
            expression_destroy(left);
            expression_destroy(right);
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        binary_expr->type = EXPR_BINARY_OP;
        binary_expr->data.binary_op.operator = op;
        binary_expr->data.binary_op.left = left;
        binary_expr->data.binary_op.right = right;
        
        left = binary_expr;
    }
    
    return left;
}

expression_t* parser_parse_unary_expression(parser_t* parser) {
    if (parser_match_token(parser, TOKEN_NOT) || 
        parser_match_token(parser, TOKEN_MINUS) ||
        parser_match_token(parser, TOKEN_PLUS)) {
        token_type_t op = parser->current_token->type;
        parser_consume_token(parser, op);
        
        expression_t* operand = parser_parse_unary_expression(parser);
        if (!operand) return NULL;
        
        expression_t* unary_expr = calloc(1, sizeof(expression_t));
        if (!unary_expr) {
            expression_destroy(operand);
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        unary_expr->type = EXPR_UNARY_OP;
        unary_expr->data.unary_op.operator = op;
        unary_expr->data.unary_op.operand = operand;
        
        return unary_expr;
    }
    
    return parser_parse_primary_expression(parser);
}

// Statement parsing (basic implementations)
statement_t* parser_parse_statement(parser_t* parser) {
    if (!parser->current_token) {
        parser_set_error(parser, "Unexpected end of input");
        return NULL;
    }
    
    switch (parser->current_token->type) {
        case TOKEN_SELECT:
            return parser_parse_select(parser);
        case TOKEN_INSERT:
            return parser_parse_insert(parser);
        case TOKEN_UPDATE:
            return parser_parse_update(parser);
        case TOKEN_DELETE:
            return parser_parse_delete(parser);
        case TOKEN_CREATE:
            // Look ahead to determine CREATE TABLE vs CREATE DATABASE vs CREATE USER vs CREATE VIEW vs CREATE OR REPLACE VIEW
            {
                token_t* next = lexer_peek_token(parser->lexer);
                if (next && next->type == TOKEN_TABLE) {
                    token_destroy(next);
                    return parser_parse_create_table(parser);
                } else if (next && next->type == TOKEN_DATABASE) {
                    token_destroy(next);
                    return parser_parse_create_database(parser);
                } else if (next && next->type == TOKEN_USER) {
                    token_destroy(next);
                    return parser_parse_create_user(parser);
                } else if (next && next->type == TOKEN_VIEW) {
                    token_destroy(next);
                    return parser_parse_create_view(parser);
                } else if (next && next->type == TOKEN_INDEX) {
                    token_destroy(next);
                    return parser_parse_create_index(parser);
                } else if (next && next->type == TOKEN_TRIGGER) {
                    token_destroy(next);
                    return parser_parse_create_trigger(parser);
                } else if (next && next->type == TOKEN_OR) {
                    // Could be CREATE OR REPLACE VIEW or CREATE OR REPLACE TRIGGER
                    token_destroy(next);
                    return parser_parse_create_view(parser);
                } else {
                    if (next) token_destroy(next);
                    parser_set_error(parser, "Expected TABLE, DATABASE, USER, VIEW, INDEX, TRIGGER, or OR after CREATE");
                    return NULL;
                }
            }
        case TOKEN_DROP:
            // Look ahead to determine DROP TABLE, DROP DATABASE, or DROP VIEW
            {
                token_t* next = lexer_peek_token(parser->lexer);
                if (next && next->type == TOKEN_VIEW) {
                    token_destroy(next);
                    return parser_parse_drop_view(parser);
                } else if (next && next->type == TOKEN_TABLE) {
                    token_destroy(next);
                    return parser_parse_drop_table(parser);
                } else if (next && next->type == TOKEN_DATABASE) {
                    token_destroy(next);
                    return parser_parse_drop_database(parser);
                } else if (next && next->type == TOKEN_INDEX) {
                    token_destroy(next);
                    return parser_parse_drop_index(parser);
                } else if (next && next->type == TOKEN_TRIGGER) {
                    token_destroy(next);
                    return parser_parse_drop_trigger(parser);
                } else {
                    if (next) token_destroy(next);
                    parser_set_error(parser, "Expected TABLE, DATABASE, VIEW, INDEX, or TRIGGER after DROP");
                    return NULL;
                }
            }
        case TOKEN_ALTER:
            return parser_parse_alter_table(parser);
        case TOKEN_GRANT:
            return parser_parse_grant(parser);
        case TOKEN_START:
        case TOKEN_COMMIT:
        case TOKEN_ROLLBACK:
            return parser_parse_transaction(parser);
        case TOKEN_USE:
            return parser_parse_use(parser);
        case TOKEN_DESCRIBE:
            return parser_parse_describe(parser);
        case TOKEN_SHOW:
            return parser_parse_show(parser);
        case TOKEN_DESC: {
            // Check if this is DESC table_name (describe) or DESC in ORDER BY
            // If it's followed by an identifier, treat it as DESCRIBE
            token_t* next = lexer_peek_token(parser->lexer);
            if (next && next->type == TOKEN_IDENTIFIER) {
                token_destroy(next);
                // Parse as DESCRIBE command
                statement_t* stmt = calloc(1, sizeof(statement_t));
                if (!stmt) {
                    parser_set_error(parser, "Out of memory");
                    return NULL;
                }
                
                stmt->type = STMT_DESCRIBE;
                stmt->line = parser->current_token->line;
                stmt->column = parser->current_token->column;
                
                // Consume DESC token
                parser_consume_token(parser, TOKEN_DESC);
                
                // Parse table name
                if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
                    statement_destroy(stmt);
                    parser_set_error(parser, "Expected table name after DESC");
                    return NULL;
                }
                
                stmt->data.describe.table_name = strdup(parser->current_token->value);
                parser_consume_token(parser, TOKEN_IDENTIFIER);
                
                return stmt;
            } else {
                if (next) token_destroy(next);
                parser_set_error(parser, "Unexpected token");
                return NULL;
            }
        }
        default:
            parser_set_error(parser, "Unexpected token");
            return NULL;
    }
}

// Basic SELECT parser (simplified)
statement_t* parser_parse_select(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_SELECT;
    
    if (!parser_consume_token(parser, TOKEN_SELECT)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected SELECT");
        return NULL;
    }
    
    // Parse select list - support multiple expressions separated by commas
    stmt->data.select.select_list = parser_parse_select_list(parser);
    if (!stmt->data.select.select_list) {
        statement_destroy(stmt);
        return NULL;
    }
    
    // FROM clause (optional)
    if (parser_match_token(parser, TOKEN_FROM)) {
        parser_consume_token(parser, TOKEN_FROM);
        
        stmt->data.select.from_list = parser_parse_from_clause(parser);
        if (!stmt->data.select.from_list) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // WHERE clause (optional)
    if (parser_match_token(parser, TOKEN_WHERE)) {
        parser_consume_token(parser, TOKEN_WHERE);
        stmt->data.select.where_clause = parser_parse_expression(parser);
        if (!stmt->data.select.where_clause) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // GROUP BY clause (optional)
    if (parser_match_token(parser, TOKEN_GROUP)) {
        if (!parser_consume_token(parser, TOKEN_GROUP)) {
            statement_destroy(stmt);
            return NULL;
        }
        
        if (!parser_consume_token(parser, TOKEN_BY)) {
            parser_set_error(parser, "Expected BY after GROUP");
            statement_destroy(stmt);
            return NULL;
        }
        
        // Parse GROUP BY expression list
        stmt->data.select.group_by = parser_parse_select_list(parser);
        if (!stmt->data.select.group_by) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // HAVING clause (optional, can only appear after GROUP BY)
    if (parser_match_token(parser, TOKEN_HAVING)) {
        if (!stmt->data.select.group_by) {
            parser_set_error(parser, "HAVING clause requires GROUP BY clause");
            statement_destroy(stmt);
            return NULL;
        }
        
        if (!parser_consume_token(parser, TOKEN_HAVING)) {
            statement_destroy(stmt);
            return NULL;
        }
        
        stmt->data.select.having = parser_parse_expression(parser);
        if (!stmt->data.select.having) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // ORDER BY clause (optional)
    if (parser_match_token(parser, TOKEN_ORDER)) {
        if (!parser_consume_token(parser, TOKEN_ORDER)) {
            statement_destroy(stmt);
            return NULL;
        }
        
        if (!parser_consume_token(parser, TOKEN_BY)) {
            parser_set_error(parser, "Expected BY after ORDER");
            statement_destroy(stmt);
            return NULL;
        }
        
        // Parse ORDER BY expression list with ASC/DESC modifiers
        stmt->data.select.order_by = parser_parse_order_by_list(parser);
        if (!stmt->data.select.order_by) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // LIMIT clause (optional)
    if (parser_match_token(parser, TOKEN_LIMIT)) {
        if (!parser_consume_token(parser, TOKEN_LIMIT)) {
            statement_destroy(stmt);
            return NULL;
        }
        
        if (!parser_match_token(parser, TOKEN_NUMBER)) {
            parser_set_error(parser, "Expected number after LIMIT");
            statement_destroy(stmt);
            return NULL;
        }
        
        stmt->data.select.limit = strtoul(parser->current_token->value, NULL, 10);
        
        if (!parser_consume_token(parser, TOKEN_NUMBER)) {
            statement_destroy(stmt);
            return NULL;
        }
        
        // OFFSET clause (optional after LIMIT)
        if (parser_match_token(parser, TOKEN_OFFSET)) {
            if (!parser_consume_token(parser, TOKEN_OFFSET)) {
                statement_destroy(stmt);
                return NULL;
            }
            
            if (!parser_match_token(parser, TOKEN_NUMBER)) {
                parser_set_error(parser, "Expected number after OFFSET");
                statement_destroy(stmt);
                return NULL;
            }
            
            stmt->data.select.offset = strtoul(parser->current_token->value, NULL, 10);
            
            if (!parser_consume_token(parser, TOKEN_NUMBER)) {
                statement_destroy(stmt);
                return NULL;
            }
        }
    }
    
    return stmt;
}

// Placeholder implementations for other statement types
statement_t* parser_parse_insert(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_INSERT;
    
    // Consume INSERT token
    if (!parser_consume_token(parser, TOKEN_INSERT)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected INSERT");
        return NULL;
    }
    
    // Consume INTO token
    if (!parser_consume_token(parser, TOKEN_INTO)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected INTO after INSERT");
        return NULL;
    }
    
    // Parse table name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected table name after INTO");
        return NULL;
    }
    
    stmt->data.insert.table_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Check for optional column list: (column1, column2, ...)
    if (parser_match_token(parser, TOKEN_LPAREN)) {
        parser_consume_token(parser, TOKEN_LPAREN);
        
        // Parse column names
        char** column_names = NULL;
        uint32_t capacity = 4;
        uint32_t count = 0;
        
        column_names = malloc(capacity * sizeof(char*));
        if (!column_names) {
            statement_destroy(stmt);
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        // Parse first column name
        if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
            free(column_names);
            statement_destroy(stmt);
            parser_set_error(parser, "Expected column name");
            return NULL;
        }
        
        column_names[count++] = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        
        // Parse additional column names
        while (parser_match_token(parser, TOKEN_COMMA)) {
            parser_consume_token(parser, TOKEN_COMMA);
            
            // Expand array if needed
            if (count >= capacity) {
                capacity *= 2;
                char** new_columns = realloc(column_names, capacity * sizeof(char*));
                if (!new_columns) {
                    // Clean up
                    for (uint32_t i = 0; i < count; i++) {
                        free(column_names[i]);
                    }
                    free(column_names);
                    statement_destroy(stmt);
                    parser_set_error(parser, "Out of memory");
                    return NULL;
                }
                column_names = new_columns;
            }
            
            if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
                // Clean up
                for (uint32_t i = 0; i < count; i++) {
                    free(column_names[i]);
                }
                free(column_names);
                statement_destroy(stmt);
                parser_set_error(parser, "Expected column name after comma");
                return NULL;
            }
            
            column_names[count++] = strdup(parser->current_token->value);
            parser_consume_token(parser, TOKEN_IDENTIFIER);
        }
        
        // Expect closing parenthesis
        if (!parser_consume_token(parser, TOKEN_RPAREN)) {
            // Clean up
            for (uint32_t i = 0; i < count; i++) {
                free(column_names[i]);
            }
            free(column_names);
            statement_destroy(stmt);
            parser_set_error(parser, "Expected ')' after column list");
            return NULL;
        }
        
        stmt->data.insert.column_names = column_names;
        stmt->data.insert.column_count = count;
    }
    
    // Expect VALUES keyword
    if (!parser_consume_token(parser, TOKEN_VALUES)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected VALUES");
        return NULL;
    }
    
    // Expect opening parenthesis for values
    if (!parser_consume_token(parser, TOKEN_LPAREN)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected '(' after VALUES");
        return NULL;
    }
    
    // Parse value expressions
    expression_t** values = NULL;
    uint32_t value_capacity = 4;
    uint32_t value_count = 0;
    
    values = malloc(value_capacity * sizeof(expression_t*));
    if (!values) {
        statement_destroy(stmt);
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    // Parse first value
    expression_t* first_value = parser_parse_expression(parser);
    if (!first_value) {
        free(values);
        statement_destroy(stmt);
        return NULL;
    }
    
    values[value_count++] = first_value;
    
    // Parse additional values
    while (parser_match_token(parser, TOKEN_COMMA)) {
        parser_consume_token(parser, TOKEN_COMMA);
        
        // Expand array if needed
        if (value_count >= value_capacity) {
            value_capacity *= 2;
            expression_t** new_values = realloc(values, value_capacity * sizeof(expression_t*));
            if (!new_values) {
                // Clean up
                for (uint32_t i = 0; i < value_count; i++) {
                    expression_destroy(values[i]);
                }
                free(values);
                statement_destroy(stmt);
                parser_set_error(parser, "Out of memory");
                return NULL;
            }
            values = new_values;
        }
        
        expression_t* next_value = parser_parse_expression(parser);
        if (!next_value) {
            // Clean up
            for (uint32_t i = 0; i < value_count; i++) {
                expression_destroy(values[i]);
            }
            free(values);
            statement_destroy(stmt);
            return NULL;
        }
        
        values[value_count++] = next_value;
    }
    
    // Expect closing parenthesis
    if (!parser_consume_token(parser, TOKEN_RPAREN)) {
        // Clean up
        for (uint32_t i = 0; i < value_count; i++) {
            expression_destroy(values[i]);
        }
        free(values);
        statement_destroy(stmt);
        parser_set_error(parser, "Expected ')' after values");
        return NULL;
    }
    
    stmt->data.insert.values = values;
    stmt->data.insert.value_count = value_count;
    
    return stmt;
}

statement_t* parser_parse_update(parser_t* parser) {
    if (!parser_consume_token(parser, TOKEN_UPDATE)) {
        return NULL;
    }
    
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (stmt) {
        stmt->type = STMT_UPDATE;
    }
    if (!stmt) {
        parser_set_error(parser, "Failed to allocate UPDATE statement");
        return NULL;
    }
    
    // Parse table name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        parser_set_error(parser, "Expected table name after UPDATE");
        statement_destroy(stmt);
        return NULL;
    }
    
    stmt->data.update.table_name = strdup(parser->current_token->value);
    if (!stmt->data.update.table_name) {
        parser_set_error(parser, "Failed to allocate table name");
        statement_destroy(stmt);
        return NULL;
    }
    
    if (!parser_consume_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        return NULL;
    }
    
    // Parse SET clause
    if (!parser_consume_token(parser, TOKEN_SET)) {
        parser_set_error(parser, "Expected SET after table name in UPDATE");
        statement_destroy(stmt);
        return NULL;
    }
    
    // Parse assignments: column = value, column = value, ...
    uint32_t capacity = 4;
    stmt->data.update.assignments = malloc(capacity * sizeof(expression_t*));
    if (!stmt->data.update.assignments) {
        parser_set_error(parser, "Failed to allocate assignments array");
        statement_destroy(stmt);
        return NULL;
    }
    
    stmt->data.update.assignment_count = 0;
    
    do {
        // Expand capacity if needed
        if (stmt->data.update.assignment_count >= capacity) {
            capacity *= 2;
            expression_t** new_assignments = realloc(stmt->data.update.assignments, 
                                                   capacity * sizeof(expression_t*));
            if (!new_assignments) {
                parser_set_error(parser, "Failed to expand assignments array");
                statement_destroy(stmt);
                return NULL;
            }
            stmt->data.update.assignments = new_assignments;
        }
        
        // Parse column = value assignment
        if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
            parser_set_error(parser, "Expected column name in SET clause");
            statement_destroy(stmt);
            return NULL;
        }
        
        // Create assignment expression as a binary operation
        expression_t* assignment = calloc(1, sizeof(expression_t));
        if (assignment) {
            assignment->type = EXPR_BINARY_OP;
        }
        if (!assignment) {
            parser_set_error(parser, "Failed to allocate assignment expression");
            statement_destroy(stmt);
            return NULL;
        }
        
        // Left side: column reference
        assignment->data.binary_op.left = calloc(1, sizeof(expression_t));
        if (assignment->data.binary_op.left) {
            assignment->data.binary_op.left->type = EXPR_COLUMN;
        }
        if (!assignment->data.binary_op.left) {
            parser_set_error(parser, "Failed to allocate column expression");
            expression_destroy(assignment);
            statement_destroy(stmt);
            return NULL;
        }
        assignment->data.binary_op.left->data.column.column_name = strdup(parser->current_token->value);
        assignment->data.binary_op.left->data.column.table_name = NULL;
        
        if (!parser_consume_token(parser, TOKEN_IDENTIFIER)) {
            expression_destroy(assignment);
            statement_destroy(stmt);
            return NULL;
        }
        
        // Parse = operator
        if (!parser_consume_token(parser, TOKEN_EQUAL)) {
            parser_set_error(parser, "Expected '=' in assignment");
            expression_destroy(assignment);
            statement_destroy(stmt);
            return NULL;
        }
        
        assignment->data.binary_op.operator = TOKEN_EQUAL;
        
        // Right side: value expression
        assignment->data.binary_op.right = parser_parse_expression(parser);
        if (!assignment->data.binary_op.right) {
            expression_destroy(assignment);
            statement_destroy(stmt);
            return NULL;
        }
        
        stmt->data.update.assignments[stmt->data.update.assignment_count++] = assignment;
        
    } while (parser_match_token(parser, TOKEN_COMMA) && parser_consume_token(parser, TOKEN_COMMA));
    
    // Parse optional WHERE clause
    if (parser_match_token(parser, TOKEN_WHERE)) {
        if (!parser_consume_token(parser, TOKEN_WHERE)) {
            statement_destroy(stmt);
            return NULL;
        }
        
        stmt->data.update.where_clause = parser_parse_expression(parser);
        if (!stmt->data.update.where_clause) {
            statement_destroy(stmt);
            return NULL;
        }
    } else {
        stmt->data.update.where_clause = NULL;
    }
    
    return stmt;
}

statement_t* parser_parse_delete(parser_t* parser) {
    if (!parser_consume_token(parser, TOKEN_DELETE)) {
        return NULL;
    }
    
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (stmt) {
        stmt->type = STMT_DELETE;
    }
    if (!stmt) {
        parser_set_error(parser, "Failed to allocate DELETE statement");
        return NULL;
    }
    
    // Parse FROM keyword
    if (!parser_consume_token(parser, TOKEN_FROM)) {
        parser_set_error(parser, "Expected FROM after DELETE");
        statement_destroy(stmt);
        return NULL;
    }
    
    // Parse table name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        parser_set_error(parser, "Expected table name after FROM");
        statement_destroy(stmt);
        return NULL;
    }
    
    stmt->data.delete.table_name = strdup(parser->current_token->value);
    if (!stmt->data.delete.table_name) {
        parser_set_error(parser, "Failed to allocate table name");
        statement_destroy(stmt);
        return NULL;
    }
    
    if (!parser_consume_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        return NULL;
    }
    
    // Parse optional WHERE clause
    if (parser_match_token(parser, TOKEN_WHERE)) {
        if (!parser_consume_token(parser, TOKEN_WHERE)) {
            statement_destroy(stmt);
            return NULL;
        }
        
        stmt->data.delete.where_clause = parser_parse_expression(parser);
        if (!stmt->data.delete.where_clause) {
            statement_destroy(stmt);
            return NULL;
        }
    } else {
        stmt->data.delete.where_clause = NULL;
    }
    
    return stmt;
}

statement_t* parser_parse_create_table(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Memory allocation failed");
        return NULL;
    }
    
    stmt->type = STMT_CREATE_TABLE;
    stmt->line = parser->current_token ? parser->current_token->line : 1;
    stmt->column = parser->current_token ? parser->current_token->column : 1;
    
    // Consume CREATE keyword
    if (!parser_consume_token(parser, TOKEN_CREATE)) {
        parser_set_error(parser, "Expected CREATE keyword");
        statement_destroy(stmt);
        return NULL;
    }
    
    // Consume TABLE keyword
    if (!parser_consume_token(parser, TOKEN_TABLE)) {
        parser_set_error(parser, "Expected TABLE keyword");
        statement_destroy(stmt);
        return NULL;
    }
    
    // Parse table name
    if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
        parser_set_error(parser, "Expected table name");
        statement_destroy(stmt);
        return NULL;
    }
    
    stmt->data.create_table.table_name = strdup(parser->current_token->value);
    if (!stmt->data.create_table.table_name) {
        parser_set_error(parser, "Memory allocation failed");
        statement_destroy(stmt);
        return NULL;
    }
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Consume opening parenthesis
    if (!parser_consume_token(parser, TOKEN_LPAREN)) {
        parser_set_error(parser, "Expected '(' after table name");
        statement_destroy(stmt);
        return NULL;
    }
    
    // Parse column definitions
    column_def_t* columns = NULL;
    column_def_t* last_column = NULL;
    uint32_t column_count = 0;
    
    while (parser->current_token && parser->current_token->type != TOKEN_RPAREN) {
        // Parse column definition
        column_def_t* col = calloc(1, sizeof(column_def_t));
        if (!col) {
            parser_set_error(parser, "Memory allocation failed");
            // Clean up columns list
            while (columns) {
                column_def_t* temp = columns;
                columns = columns->next;
                column_def_destroy(temp);
            }
            statement_destroy(stmt);
            return NULL;
        }
        
        // Parse column name
        if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
            parser_set_error(parser, "Expected column name");
            column_def_destroy(col);
            statement_destroy(stmt);
            return NULL;
        }
        
        col->name = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        
        // Parse column type
        if (!parser->current_token) {
            parser_set_error(parser, "Expected column type");
            column_def_destroy(col);
            statement_destroy(stmt);
            return NULL;
        }
        
        // Map token type to data type
        switch (parser->current_token->type) {
            case TOKEN_INT:
                col->type = DATA_TYPE_INT;
                break;
            case TOKEN_TINYINT:
                col->type = DATA_TYPE_TINYINT;
                break;
            case TOKEN_BIGINT:
                col->type = DATA_TYPE_BIGINT;
                break;
            case TOKEN_FLOAT:
                col->type = DATA_TYPE_FLOAT;
                break;
            case TOKEN_VARCHAR:
                col->type = DATA_TYPE_VARCHAR;
                parser_consume_token(parser, TOKEN_VARCHAR);
                // Parse length specification
                if (parser->current_token && parser->current_token->type == TOKEN_LPAREN) {
                    parser_consume_token(parser, TOKEN_LPAREN);
                    if (parser->current_token && parser->current_token->type == TOKEN_NUMBER) {
                        col->length = atoi(parser->current_token->value);
                        parser_consume_token(parser, TOKEN_NUMBER);
                        if (parser->current_token && parser->current_token->type == TOKEN_RPAREN) {
                            parser_consume_token(parser, TOKEN_RPAREN);
                        }
                    }
                }
                goto skip_next_token;
            case TOKEN_DOUBLE:
                col->type = DATA_TYPE_DOUBLE;
                parser_consume_token(parser, TOKEN_DOUBLE);
                // Skip precision/scale specification for now
                if (parser->current_token && parser->current_token->type == TOKEN_LPAREN) {
                    int paren_count = 1;
                    parser_consume_token(parser, TOKEN_LPAREN);
                    while (parser->current_token && paren_count > 0) {
                        if (parser->current_token->type == TOKEN_LPAREN) paren_count++;
                        else if (parser->current_token->type == TOKEN_RPAREN) paren_count--;
                        lexer_next_token(parser->lexer); // consume any token type
                        parser->current_token = parser->lexer->current_token;
                    }
                }
                goto skip_next_token;
            default:
                parser_set_error(parser, "Unsupported column type");
                column_def_destroy(col);
                statement_destroy(stmt);
                return NULL;
        }
        parser_consume_token(parser, parser->current_token->type);
        
        skip_next_token:
        
        // Parse column constraints
        while (parser->current_token && 
               (parser->current_token->type == TOKEN_NOT ||
                parser->current_token->type == TOKEN_PRIMARY ||
                parser->current_token->type == TOKEN_UNIQUE ||
                parser->current_token->type == TOKEN_DEFAULT)) {
            
            if (parser->current_token->type == TOKEN_NOT) {
                parser_consume_token(parser, TOKEN_NOT);
                if (parser->current_token && parser->current_token->type == TOKEN_NULL) {
                    col->not_null = true;
                    parser_consume_token(parser, TOKEN_NULL);
                }
            } else if (parser->current_token->type == TOKEN_PRIMARY) {
                parser_consume_token(parser, TOKEN_PRIMARY);
                if (parser->current_token && parser->current_token->type == TOKEN_KEY) {
                    col->primary_key = true;
                    parser_consume_token(parser, TOKEN_KEY);
                }
            } else if (parser->current_token->type == TOKEN_UNIQUE) {
                col->unique = true;
                parser_consume_token(parser, TOKEN_UNIQUE);
            } else if (parser->current_token->type == TOKEN_DEFAULT) {
                parser_consume_token(parser, TOKEN_DEFAULT);
                // Parse default value - can be number, string, NULL, etc.
                if (parser->current_token && 
                    (parser->current_token->type == TOKEN_NUMBER ||
                     parser->current_token->type == TOKEN_STRING ||
                     parser->current_token->type == TOKEN_NULL)) {
                    col->default_value = strdup(parser->current_token->value);
                    parser_consume_token(parser, parser->current_token->type);
                }
            }
        }
        
        // Add column to list
        if (!columns) {
            columns = col;
            last_column = col;
        } else {
            last_column->next = col;
            last_column = col;
        }
        column_count++;
        
        // Check for comma or closing parenthesis
        if (parser->current_token && parser->current_token->type == TOKEN_COMMA) {
            parser_consume_token(parser, TOKEN_COMMA);
        } else if (parser->current_token && parser->current_token->type == TOKEN_RPAREN) {
            break;
        } else {
            parser_set_error(parser, "Expected ',' or ')'");
            // Clean up
            while (columns) {
                column_def_t* temp = columns;
                columns = columns->next;
                column_def_destroy(temp);
            }
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // Consume closing parenthesis
    if (!parser_consume_token(parser, TOKEN_RPAREN)) {
        parser_set_error(parser, "Expected ')' after column definitions");
        // Clean up
        while (columns) {
            column_def_t* temp = columns;
            columns = columns->next;
            column_def_destroy(temp);
        }
        statement_destroy(stmt);
        return NULL;
    }
    
    // Store column definitions in statement
    stmt->data.create_table.columns = columns;
    
    return stmt;
}

statement_t* parser_parse_create_database(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Memory allocation failed");
        return NULL;
    }
    
    stmt->type = STMT_CREATE_DATABASE;
    stmt->data.create_database.if_not_exists = false;
    
    // Consume CREATE keyword
    if (!parser_consume_token(parser, TOKEN_CREATE)) {
        parser_set_error(parser, "Expected CREATE keyword");
        statement_destroy(stmt);
        return NULL;
    }
    
    // Consume DATABASE keyword
    if (!parser_consume_token(parser, TOKEN_DATABASE)) {
        parser_set_error(parser, "Expected DATABASE keyword");
        statement_destroy(stmt);
        return NULL;
    }
    
    // Check for optional IF NOT EXISTS
    if (parser_match_token(parser, TOKEN_IF)) {
        parser_consume_token(parser, TOKEN_IF);
        if (!parser_consume_token(parser, TOKEN_NOT)) {
            parser_set_error(parser, "Expected NOT after IF");
            statement_destroy(stmt);
            return NULL;
        }
        if (!parser_consume_token(parser, TOKEN_EXISTS)) {
            parser_set_error(parser, "Expected EXISTS after IF NOT");
            statement_destroy(stmt);
            return NULL;
        }
        stmt->data.create_database.if_not_exists = true;
    }
    
    // Parse database name
    if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
        parser_set_error(parser, "Expected database name");
        statement_destroy(stmt);
        return NULL;
    }
    
    stmt->data.create_database.database_name = strdup(parser->current_token->value);
    if (!stmt->data.create_database.database_name) {
        parser_set_error(parser, "Memory allocation failed");
        statement_destroy(stmt);
        return NULL;
    }
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    return stmt;
}

statement_t* parser_parse_create_user(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_CREATE_USER;
    
    // Consume CREATE token
    if (!parser_consume_token(parser, TOKEN_CREATE)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected CREATE");
        return NULL;
    }
    
    // Consume USER token
    if (!parser_consume_token(parser, TOKEN_USER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected USER");
        return NULL;
    }
    
    // Parse username
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected username");
        return NULL;
    }
    
    stmt->data.create_user.username = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Parse IDENTIFIED BY password
    if (parser_match_token(parser, TOKEN_IDENTIFIED)) {
        parser_consume_token(parser, TOKEN_IDENTIFIED);
        
        if (!parser_match_token(parser, TOKEN_BY)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected BY after IDENTIFIED");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_BY);
        
        if (!parser_match_token(parser, TOKEN_STRING)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected password string");
            return NULL;
        }
        
        stmt->data.create_user.password = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_STRING);
    }
    
    // Optional role specification (admin, read_write, read_only)
    if (parser_match_token(parser, TOKEN_IDENTIFIER) &&
        (strcasecmp(parser->current_token->value, "ADMIN") == 0 ||
         strcasecmp(parser->current_token->value, "READ_WRITE") == 0 ||
         strcasecmp(parser->current_token->value, "READ_ONLY") == 0)) {
        stmt->data.create_user.role = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
    } else {
        // Default role is read_write
        stmt->data.create_user.role = strdup("READ_WRITE");
    }
    
    return stmt;
}

statement_t* parser_parse_grant(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_GRANT;
    
    // Consume GRANT token
    if (!parser_consume_token(parser, TOKEN_GRANT)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected GRANT");
        return NULL;
    }
    
    // Parse permission list (SELECT, INSERT, UPDATE, DELETE, ALL)
    uint8_t permissions = 0;
    bool first_permission = true;
    
    do {
        if (!first_permission) {
            if (!parser_match_token(parser, TOKEN_COMMA)) {
                break;
            }
            parser_consume_token(parser, TOKEN_COMMA);
        }
        
        if (parser_match_token(parser, TOKEN_SELECT)) {
            permissions |= GU_PERM_SELECT;
            parser_consume_token(parser, TOKEN_SELECT);
        } else if (parser_match_token(parser, TOKEN_INSERT)) {
            permissions |= GU_PERM_INSERT;
            parser_consume_token(parser, TOKEN_INSERT);
        } else if (parser_match_token(parser, TOKEN_UPDATE)) {
            permissions |= GU_PERM_UPDATE;
            parser_consume_token(parser, TOKEN_UPDATE);
        } else if (parser_match_token(parser, TOKEN_DELETE)) {
            permissions |= GU_PERM_DELETE;
            parser_consume_token(parser, TOKEN_DELETE);
        } else if (parser_match_token(parser, TOKEN_ALL)) {
            permissions |= GU_PERM_ALL;
            parser_consume_token(parser, TOKEN_ALL);
        } else if (first_permission) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected permission (SELECT, INSERT, UPDATE, DELETE, ALL)");
            return NULL;
        } else {
            break;
        }
        
        first_permission = false;
    } while (true);
    
    stmt->data.grant.permissions = permissions;
    
    // Parse ON table_name
    if (!parser_match_token(parser, TOKEN_ON)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected ON after permissions");
        return NULL;
    }
    parser_consume_token(parser, TOKEN_ON);
    
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected table name after ON");
        return NULL;
    }
    
    stmt->data.grant.table_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Parse TO username
    if (!parser_match_token(parser, TOKEN_IDENTIFIER) ||
        strcasecmp(parser->current_token->value, "TO") != 0) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected TO after table name");
        return NULL;
    }
    parser_consume_token(parser, TOKEN_IDENTIFIER); // TO
    
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected username after TO");
        return NULL;
    }
    
    stmt->data.grant.username = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    return stmt;
}

statement_t* parser_parse_transaction(parser_t* parser) {
    if (!parser || !parser->current_token) {
        return NULL;
    }
    
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    // Determine transaction type based on current token
    switch (parser->current_token->type) {
        case TOKEN_START:
            // START TRANSACTION [WITH ISOLATION LEVEL ...]
            stmt->type = STMT_START_TRANSACTION;
            
            // Consume START token
            if (!parser_consume_token(parser, TOKEN_START)) {
                statement_destroy(stmt);
                return NULL;
            }
            
            // Expect TRANSACTION keyword
            if (!parser_consume_token(parser, TOKEN_TRANSACTION)) {
                parser_set_error(parser, "Expected TRANSACTION after START");
                statement_destroy(stmt);
                return NULL;
            }
            
            // Parse optional isolation level
            stmt->data.transaction.isolation_level = 1; // Default isolation level
            
            if (parser_match_token(parser, TOKEN_WITH)) {
                parser_consume_token(parser, TOKEN_WITH);
                
                if (!parser_consume_token(parser, TOKEN_ISOLATION)) {
                    parser_set_error(parser, "Expected ISOLATION after WITH");
                    statement_destroy(stmt);
                    return NULL;
                }
                
                if (!parser_consume_token(parser, TOKEN_LEVEL)) {
                    parser_set_error(parser, "Expected LEVEL after ISOLATION");
                    statement_destroy(stmt);
                    return NULL;
                }
                
                // Parse isolation level
                if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
                    parser_set_error(parser, "Expected isolation level (READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE)");
                    statement_destroy(stmt);
                    return NULL;
                }
                
                const char* level_str = parser->current_token->value;
                if (strcasecmp(level_str, "READ UNCOMMITTED") == 0) {
                    stmt->data.transaction.isolation_level = 0;
                } else if (strcasecmp(level_str, "READ COMMITTED") == 0) {
                    stmt->data.transaction.isolation_level = 1;
                } else if (strcasecmp(level_str, "REPEATABLE READ") == 0) {
                    stmt->data.transaction.isolation_level = 2;
                } else if (strcasecmp(level_str, "SERIALIZABLE") == 0) {
                    stmt->data.transaction.isolation_level = 3;
                } else {
                    parser_set_error(parser, "Invalid isolation level. Expected: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE");
                    statement_destroy(stmt);
                    return NULL;
                }
                
                parser_consume_token(parser, TOKEN_IDENTIFIER);
            }
            break;
            
        case TOKEN_COMMIT:
            // COMMIT [WORK]
            stmt->type = STMT_COMMIT;
            stmt->data.transaction.isolation_level = 0; // Not used for COMMIT
            
            // Consume COMMIT token
            if (!parser_consume_token(parser, TOKEN_COMMIT)) {
                statement_destroy(stmt);
                return NULL;
            }
            
            // Optional WORK keyword (standard SQL but optional)
            if (parser_match_token(parser, TOKEN_WORK)) {
                parser_consume_token(parser, TOKEN_WORK);
            }
            break;
            
        case TOKEN_ROLLBACK:
            // ROLLBACK [WORK] [TO SAVEPOINT savepoint_name]
            stmt->type = STMT_ROLLBACK;
            stmt->data.transaction.isolation_level = 0; // Not used for ROLLBACK
            
            // Consume ROLLBACK token
            if (!parser_consume_token(parser, TOKEN_ROLLBACK)) {
                statement_destroy(stmt);
                return NULL;
            }
            
            // Optional WORK keyword
            if (parser_match_token(parser, TOKEN_WORK)) {
                parser_consume_token(parser, TOKEN_WORK);
            }
            
            // Optional TO SAVEPOINT clause (not implemented in basic version)
            if (parser_match_token(parser, TOKEN_TO)) {
                parser_set_error(parser, "SAVEPOINT clauses not yet supported in ROLLBACK");
                statement_destroy(stmt);
                return NULL;
            }
            break;
            
        default:
            parser_set_error(parser, "Expected START, COMMIT, or ROLLBACK");
            statement_destroy(stmt);
            return NULL;
    }
    
    return stmt;
}

// Memory management functions
void expression_destroy(expression_t* expr) {
    if (!expr) return;
    
    switch (expr->type) {
        case EXPR_COLUMN:
            if (expr->data.column.table_name) free(expr->data.column.table_name);
            if (expr->data.column.column_name) free(expr->data.column.column_name);
            break;
        case EXPR_LITERAL:
            if (expr->data.literal.value) free(expr->data.literal.value);
            break;
        case EXPR_BINARY_OP:
            expression_destroy(expr->data.binary_op.left);
            expression_destroy(expr->data.binary_op.right);
            break;
        case EXPR_UNARY_OP:
            expression_destroy(expr->data.unary_op.operand);
            break;
        case EXPR_LIST:
            if (expr->data.list.expressions) {
                for (uint32_t i = 0; i < expr->data.list.count; i++) {
                    expression_destroy(expr->data.list.expressions[i]);
                }
                free(expr->data.list.expressions);
            }
            break;
        case EXPR_FUNCTION_CALL:
            if (expr->data.function_call.function_name) {
                free(expr->data.function_call.function_name);
            }
            if (expr->data.function_call.args) {
                for (uint32_t i = 0; i < expr->data.function_call.arg_count; i++) {
                    expression_destroy(expr->data.function_call.args[i]);
                }
                free(expr->data.function_call.args);
            }
            break;
        case EXPR_SUBQUERY:
            if (expr->data.subquery.query) {
                statement_destroy(expr->data.subquery.query);
            }
            if (expr->data.subquery.correlation_refs) {
                for (uint32_t i = 0; i < expr->data.subquery.correlation_count; i++) {
                    free(expr->data.subquery.correlation_refs[i]);
                }
                free(expr->data.subquery.correlation_refs);
            }
            break;
        // Add other cases as needed
        default:
            break;
    }
    
    free(expr);
}

void statement_destroy(statement_t* stmt) {
    if (!stmt) return;
    
    switch (stmt->type) {
        case STMT_SELECT:
            expression_destroy(stmt->data.select.select_list);
            expression_destroy(stmt->data.select.where_clause);
            expression_destroy(stmt->data.select.group_by);
            expression_destroy(stmt->data.select.having);
            order_by_item_destroy(stmt->data.select.order_by);
            table_ref_destroy(stmt->data.select.from_list);
            break;
        case STMT_INSERT:
            if (stmt->data.insert.table_name) {
                free(stmt->data.insert.table_name);
            }
            if (stmt->data.insert.column_names) {
                for (uint32_t i = 0; i < stmt->data.insert.column_count; i++) {
                    if (stmt->data.insert.column_names[i]) {
                        free(stmt->data.insert.column_names[i]);
                    }
                }
                free(stmt->data.insert.column_names);
            }
            if (stmt->data.insert.values) {
                for (uint32_t i = 0; i < stmt->data.insert.value_count; i++) {
                    expression_destroy(stmt->data.insert.values[i]);
                }
                free(stmt->data.insert.values);
            }
            break;
        case STMT_UPDATE:
            if (stmt->data.update.table_name) {
                free(stmt->data.update.table_name);
            }
            if (stmt->data.update.assignments) {
                for (uint32_t i = 0; i < stmt->data.update.assignment_count; i++) {
                    expression_destroy(stmt->data.update.assignments[i]);
                }
                free(stmt->data.update.assignments);
            }
            expression_destroy(stmt->data.update.where_clause);
            break;
        case STMT_DELETE:
            if (stmt->data.delete.table_name) {
                free(stmt->data.delete.table_name);
            }
            expression_destroy(stmt->data.delete.where_clause);
            break;
        case STMT_CREATE_VIEW:
            if (stmt->data.create_view.view_name) {
                free(stmt->data.create_view.view_name);
            }
            expression_destroy(stmt->data.create_view.select_list);
            expression_destroy(stmt->data.create_view.where_clause);
            expression_destroy(stmt->data.create_view.group_by);
            expression_destroy(stmt->data.create_view.having);
            order_by_item_destroy(stmt->data.create_view.order_by);
            table_ref_destroy(stmt->data.create_view.from_list);
            break;
        // Add other cases as needed
        default:
            break;
    }
    
    free(stmt);
}

void table_ref_destroy(table_ref_t* table) {
    if (!table) return;
    
    if (table->table_name) free(table->table_name);
    if (table->alias) free(table->alias);
    expression_destroy(table->join_condition);
    
    if (table->next) {
        table_ref_destroy(table->next);
    }
    
    free(table);
}

void column_def_destroy(column_def_t* col) {
    if (!col) return;
    
    if (col->name) free(col->name);
    if (col->default_value) free(col->default_value);
    
    if (col->next) {
        column_def_destroy(col->next);
    }
    
    free(col);
}

// Utility functions (basic implementations)
const char* token_type_to_string(token_type_t type) {
    switch (type) {
        case TOKEN_SELECT: return "SELECT";
        case TOKEN_FROM: return "FROM";
        case TOKEN_WHERE: return "WHERE";
        case TOKEN_INSERT: return "INSERT";
        case TOKEN_INTO: return "INTO";
        case TOKEN_VALUES: return "VALUES";
        case TOKEN_UPDATE: return "UPDATE";
        case TOKEN_SET: return "SET";
        case TOKEN_DELETE: return "DELETE";
        case TOKEN_CREATE: return "CREATE";
        case TOKEN_TABLE: return "TABLE";
        case TOKEN_AND: return "AND";
        case TOKEN_OR: return "OR";
        case TOKEN_NOT: return "NOT";
        case TOKEN_IDENTIFIER: return "IDENTIFIER";
        case TOKEN_STRING: return "STRING";
        case TOKEN_NUMBER: return "NUMBER";
        case TOKEN_EQUAL: return "=";
        case TOKEN_NOT_EQUAL: return "!=";
        case TOKEN_LESS_THAN: return "<";
        case TOKEN_LESS_EQUAL: return "<=";
        case TOKEN_GREATER_THAN: return ">";
        case TOKEN_GREATER_EQUAL: return ">=";
        case TOKEN_PLUS: return "+";
        case TOKEN_MINUS: return "-";
        case TOKEN_MULTIPLY: return "*";
        case TOKEN_DIVIDE: return "/";
        case TOKEN_COMMA: return ",";
        case TOKEN_DOT: return ".";
        case TOKEN_SEMICOLON: return ";";
        case TOKEN_LPAREN: return "(";
        case TOKEN_RPAREN: return ")";
        case TOKEN_EOF: return "EOF";
        default: return "UNKNOWN";
    }
}

const char* stmt_type_to_string(stmt_type_t type) {
    switch (type) {
        case STMT_SELECT: return "SELECT";
        case STMT_INSERT: return "INSERT";
        case STMT_UPDATE: return "UPDATE";
        case STMT_DELETE: return "DELETE";
        default: return "UNKNOWN";
    }
}

const char* expr_type_to_string(expr_type_t type) {
    switch (type) {
        case EXPR_COLUMN: return "COLUMN";
        case EXPR_LITERAL: return "LITERAL";
        case EXPR_BINARY_OP: return "BINARY_OP";
        case EXPR_UNARY_OP: return "UNARY_OP";
        case EXPR_STAR: return "STAR";
        case EXPR_LIST: return "LIST";
        default: return "UNKNOWN";
    }
}

// Parse SELECT list - supports multiple expressions separated by commas
expression_t* parser_parse_select_list(parser_t* parser) {
    if (!parser) return NULL;
    
    // Start with a dynamic array to collect expressions
    expression_t** expressions = NULL;
    uint32_t capacity = 4;  // Initial capacity
    uint32_t count = 0;
    
    expressions = malloc(capacity * sizeof(expression_t*));
    if (!expressions) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    // Parse the first expression
    expression_t* first_expr = parser_parse_expression(parser);
    if (!first_expr) {
        free(expressions);
        return NULL;
    }
    
    expressions[count++] = first_expr;
    
    // Parse additional expressions separated by commas
    while (parser_match_token(parser, TOKEN_COMMA)) {
        parser_consume_token(parser, TOKEN_COMMA);
        
        // Expand array if needed
        if (count >= capacity) {
            capacity *= 2;
            expression_t** new_expressions = realloc(expressions, capacity * sizeof(expression_t*));
            if (!new_expressions) {
                // Clean up allocated expressions
                for (uint32_t i = 0; i < count; i++) {
                    expression_destroy(expressions[i]);
                }
                free(expressions);
                parser_set_error(parser, "Out of memory");
                return NULL;
            }
            expressions = new_expressions;
        }
        
        expression_t* next_expr = parser_parse_expression(parser);
        if (!next_expr) {
            // Clean up allocated expressions
            for (uint32_t i = 0; i < count; i++) {
                expression_destroy(expressions[i]);
            }
            free(expressions);
            return NULL;
        }
        
        expressions[count++] = next_expr;
    }
    
    // If we only have one expression, return it directly (no need for list wrapper)
    if (count == 1) {
        expression_t* single_expr = expressions[0];
        free(expressions);
        return single_expr;
    }
    
    // Create a list expression to hold multiple expressions
    expression_t* list_expr = calloc(1, sizeof(expression_t));
    if (!list_expr) {
        // Clean up allocated expressions
        for (uint32_t i = 0; i < count; i++) {
            expression_destroy(expressions[i]);
        }
        free(expressions);
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    list_expr->type = EXPR_LIST;
    list_expr->data.list.expressions = expressions;
    list_expr->data.list.count = count;
    
    return list_expr;
}

// Parse FROM clause with JOIN support
table_ref_t* parser_parse_from_clause(parser_t* parser) {
    if (!parser) return NULL;
    
    // Parse the first table
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        parser_set_error(parser, "Expected table name after FROM");
        return NULL;
    }
    
    table_ref_t* first_table = calloc(1, sizeof(table_ref_t));
    if (!first_table) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    first_table->table_name = strdup(parser->current_token->value);
    if (!first_table->table_name) {
        free(first_table);
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    if (!parser_consume_token(parser, TOKEN_IDENTIFIER)) {
        table_ref_destroy(first_table);
        return NULL;
    }
    
    // Check for table alias
    if (parser_match_token(parser, TOKEN_IDENTIFIER)) {
        first_table->alias = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
    }
    
    table_ref_t* current_table = first_table;
    
    // Parse JOIN clauses
    while (parser_match_token(parser, TOKEN_INNER) || parser_match_token(parser, TOKEN_JOIN)) {
        table_ref_t* join_table = calloc(1, sizeof(table_ref_t));
        if (!join_table) {
            parser_set_error(parser, "Out of memory");
            table_ref_destroy(first_table);
            return NULL;
        }
        
        // Handle INNER JOIN or just JOIN
        if (parser_match_token(parser, TOKEN_INNER)) {
            if (!parser_consume_token(parser, TOKEN_INNER)) {
                table_ref_destroy(join_table);
                table_ref_destroy(first_table);
                return NULL;
            }
            
            if (!parser_consume_token(parser, TOKEN_JOIN)) {
                parser_set_error(parser, "Expected JOIN after INNER");
                table_ref_destroy(join_table);
                table_ref_destroy(first_table);
                return NULL;
            }
            
            join_table->join_type = TOKEN_INNER;
        } else if (parser_match_token(parser, TOKEN_JOIN)) {
            if (!parser_consume_token(parser, TOKEN_JOIN)) {
                table_ref_destroy(join_table);
                table_ref_destroy(first_table);
                return NULL;
            }
            
            join_table->join_type = TOKEN_JOIN;
        }
        
        // Parse table name
        if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
            parser_set_error(parser, "Expected table name after JOIN");
            table_ref_destroy(join_table);
            table_ref_destroy(first_table);
            return NULL;
        }
        
        join_table->table_name = strdup(parser->current_token->value);
        if (!join_table->table_name) {
            parser_set_error(parser, "Out of memory");
            table_ref_destroy(join_table);
            table_ref_destroy(first_table);
            return NULL;
        }
        
        if (!parser_consume_token(parser, TOKEN_IDENTIFIER)) {
            table_ref_destroy(join_table);
            table_ref_destroy(first_table);
            return NULL;
        }
        
        // Check for table alias
        if (parser_match_token(parser, TOKEN_IDENTIFIER)) {
            join_table->alias = strdup(parser->current_token->value);
            parser_consume_token(parser, TOKEN_IDENTIFIER);
        }
        
        // Parse ON condition
        if (!parser_consume_token(parser, TOKEN_ON)) {
            parser_set_error(parser, "Expected ON after JOIN table name");
            table_ref_destroy(join_table);
            table_ref_destroy(first_table);
            return NULL;
        }
        
        join_table->join_condition = parser_parse_expression(parser);
        if (!join_table->join_condition) {
            table_ref_destroy(join_table);
            table_ref_destroy(first_table);
            return NULL;
        }
        
        // Link the join table to the chain
        current_table->next = join_table;
        current_table = join_table;
    }
    
    return first_table;
}

// Helper function to check if an expression is a list
bool expression_is_list(expression_t* expr) {
    return expr && expr->type == EXPR_LIST;
}

// Helper function to get the count of expressions in a list (or 1 for single expression)
uint32_t expression_get_count(expression_t* expr) {
    if (!expr) return 0;
    if (expr->type == EXPR_LIST) {
        return expr->data.list.count;
    }
    return 1;
}

// Helper function to get the nth expression from a list (or the expression itself if n=0)
expression_t* expression_get_nth(expression_t* expr, uint32_t index) {
    if (!expr) return NULL;
    if (expr->type == EXPR_LIST) {
        if (index < expr->data.list.count) {
            return expr->data.list.expressions[index];
        }
        return NULL;
    }
    return (index == 0) ? expr : NULL;
}

// CREATE VIEW parser
statement_t* parser_parse_create_view(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_CREATE_VIEW;
    
    // Consume CREATE token
    if (!parser_consume_token(parser, TOKEN_CREATE)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected CREATE");
        return NULL;
    }
    
    // Check for OR REPLACE option
    if (parser_match_token(parser, TOKEN_OR)) {
        parser_consume_token(parser, TOKEN_OR);
        if (!parser_match_token(parser, TOKEN_IDENTIFIER) || 
            strcasecmp(parser->current_token->value, "REPLACE") != 0) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected REPLACE after OR");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        stmt->data.create_view.or_replace = true;
    }
    
    // Check if it's TRIGGER instead of VIEW (for CREATE OR REPLACE TRIGGER)
    if (parser_match_token(parser, TOKEN_TRIGGER)) {
        // This is actually a trigger statement
        statement_destroy(stmt);
        
        // The current parser has already consumed CREATE and OR REPLACE
        // We need to start the trigger parser from the TRIGGER token
        // Let's modify the trigger parser to handle this case
        
        // Create a new trigger statement
        statement_t* trigger_stmt = calloc(1, sizeof(statement_t));
        if (!trigger_stmt) {
            parser_set_error(parser, "Out of memory");
            return NULL;
        }
        
        trigger_stmt->type = STMT_CREATE_TRIGGER;
        trigger_stmt->data.create_trigger.or_replace = true;  // We know this is OR REPLACE
        
        // Now continue with the trigger parsing from TRIGGER token
        // Consume TRIGGER token
        if (!parser_consume_token(parser, TOKEN_TRIGGER)) {
            statement_destroy(trigger_stmt);
            parser_set_error(parser, "Expected TRIGGER");
            return NULL;
        }
        
        // Parse trigger name
        if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
            statement_destroy(trigger_stmt);
            parser_set_error(parser, "Expected trigger name");
            return NULL;
        }
        
        trigger_stmt->data.create_trigger.trigger_name = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        
        // Continue with the rest of the trigger parsing logic...
        // This is getting complex, let me use a different approach
        statement_destroy(trigger_stmt);
        parser_set_error(parser, "CREATE OR REPLACE TRIGGER not fully supported yet");
        return NULL;
    }
    
    // Consume VIEW token
    if (!parser_consume_token(parser, TOKEN_VIEW)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected VIEW");
        return NULL;
    }
    
    // Parse view name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected view name");
        return NULL;
    }
    
    stmt->data.create_view.view_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Expect AS keyword
    if (!parser_match_token(parser, TOKEN_AS)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected AS after view name");
        return NULL;
    }
    parser_consume_token(parser, TOKEN_AS);
    
    // Parse the SELECT statement that defines the view
    if (!parser_match_token(parser, TOKEN_SELECT)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected SELECT statement after AS");
        return NULL;
    }
    
    // Parse SELECT list
    parser_consume_token(parser, TOKEN_SELECT);
    stmt->data.create_view.select_list = parser_parse_select_list(parser);
    if (!stmt->data.create_view.select_list) {
        statement_destroy(stmt);
        return NULL;
    }
    
    // FROM clause (required for views)
    if (!parser_match_token(parser, TOKEN_FROM)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected FROM clause in view definition");
        return NULL;
    }
    parser_consume_token(parser, TOKEN_FROM);
    
    stmt->data.create_view.from_list = parser_parse_from_clause(parser);
    if (!stmt->data.create_view.from_list) {
        statement_destroy(stmt);
        return NULL;
    }
    
    // Optional WHERE clause
    if (parser_match_token(parser, TOKEN_WHERE)) {
        parser_consume_token(parser, TOKEN_WHERE);
        stmt->data.create_view.where_clause = parser_parse_expression(parser);
        if (!stmt->data.create_view.where_clause) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // Optional GROUP BY clause
    if (parser_match_token(parser, TOKEN_GROUP)) {
        parser_consume_token(parser, TOKEN_GROUP);
        if (!parser_consume_token(parser, TOKEN_BY)) {
            parser_set_error(parser, "Expected BY after GROUP");
            statement_destroy(stmt);
            return NULL;
        }
        stmt->data.create_view.group_by = parser_parse_select_list(parser);
        if (!stmt->data.create_view.group_by) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // Optional HAVING clause
    if (parser_match_token(parser, TOKEN_HAVING)) {
        if (!stmt->data.create_view.group_by) {
            parser_set_error(parser, "HAVING clause requires GROUP BY clause");
            statement_destroy(stmt);
            return NULL;
        }
        parser_consume_token(parser, TOKEN_HAVING);
        stmt->data.create_view.having = parser_parse_expression(parser);
        if (!stmt->data.create_view.having) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    // Optional ORDER BY clause
    if (parser_match_token(parser, TOKEN_ORDER)) {
        parser_consume_token(parser, TOKEN_ORDER);
        if (!parser_consume_token(parser, TOKEN_BY)) {
            parser_set_error(parser, "Expected BY after ORDER");
            statement_destroy(stmt);
            return NULL;
        }
        stmt->data.create_view.order_by = parser_parse_order_by_list(parser);
        if (!stmt->data.create_view.order_by) {
            statement_destroy(stmt);
            return NULL;
        }
    }
    
    return stmt;
}

// CREATE INDEX parser
statement_t* parser_parse_create_index(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_CREATE_INDEX;
    
    // Consume CREATE token
    if (!parser_consume_token(parser, TOKEN_CREATE)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected CREATE");
        return NULL;
    }
    
    // Check for UNIQUE (optional)
    if (parser->current_token && parser->current_token->type == TOKEN_UNIQUE) {
        stmt->data.create_index.unique = true;
        token_destroy(parser->current_token);
        parser->current_token = lexer_next_token(parser->lexer);
    }
    
    // Consume INDEX token  
    if (!parser_consume_token(parser, TOKEN_INDEX)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected INDEX");
        return NULL;
    }
    
    // Check for IF NOT EXISTS (optional)
    if (parser->current_token && parser->current_token->type == TOKEN_IF) {
        token_destroy(parser->current_token);
        parser->current_token = lexer_next_token(parser->lexer);
        
        if (!parser_consume_token(parser, TOKEN_NOT)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected NOT after IF");
            return NULL;
        }
        
        if (!parser_consume_token(parser, TOKEN_EXISTS)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected EXISTS after NOT");
            return NULL;
        }
        
        stmt->data.create_index.if_not_exists = true;
    }
    
    // Parse index name
    if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected index name");
        return NULL;
    }
    
    stmt->data.create_index.index_name = strdup(parser->current_token->value);
    token_destroy(parser->current_token);
    parser->current_token = lexer_next_token(parser->lexer);
    
    // Consume ON token
    if (!parser_consume_token(parser, TOKEN_ON)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected ON after index name");
        return NULL;
    }
    
    // Parse table name
    if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected table name");
        return NULL;
    }
    
    stmt->data.create_index.table_name = strdup(parser->current_token->value);
    token_destroy(parser->current_token);
    parser->current_token = lexer_next_token(parser->lexer);
    
    // Consume opening parenthesis
    if (!parser_consume_token(parser, TOKEN_LPAREN)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected '(' after table name");
        return NULL;
    }
    
    // Parse column list
    uint32_t column_capacity = 10;
    stmt->data.create_index.column_names = malloc(column_capacity * sizeof(char*));
    if (!stmt->data.create_index.column_names) {
        statement_destroy(stmt);
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    do {
        if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected column name");
            return NULL;
        }
        
        // Resize array if needed
        if (stmt->data.create_index.column_count >= column_capacity) {
            column_capacity *= 2;
            char** new_columns = realloc(stmt->data.create_index.column_names, 
                                       column_capacity * sizeof(char*));
            if (!new_columns) {
                statement_destroy(stmt);
                parser_set_error(parser, "Out of memory");
                return NULL;
            }
            stmt->data.create_index.column_names = new_columns;
        }
        
        stmt->data.create_index.column_names[stmt->data.create_index.column_count] = 
            strdup(parser->current_token->value);
        stmt->data.create_index.column_count++;
        
        token_destroy(parser->current_token);
        parser->current_token = lexer_next_token(parser->lexer);
        
        if (parser->current_token && parser->current_token->type == TOKEN_COMMA) {
            token_destroy(parser->current_token);
            parser->current_token = lexer_next_token(parser->lexer);
        } else {
            break;
        }
    } while (parser->current_token);
    
    // Consume closing parenthesis
    if (!parser_consume_token(parser, TOKEN_RPAREN)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected ')' after column list");
        return NULL;
    }
    
    return stmt;
}

// DROP VIEW parser
statement_t* parser_parse_drop_view(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_DROP_VIEW;
    
    // Consume DROP token
    if (!parser_consume_token(parser, TOKEN_DROP)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected DROP");
        return NULL;
    }
    
    // Consume VIEW token
    if (!parser_consume_token(parser, TOKEN_VIEW)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected VIEW");
        return NULL;
    }
    
    // Check for IF EXISTS option
    if (parser_match_token(parser, TOKEN_IF)) {
        parser_consume_token(parser, TOKEN_IF);
        if (!parser_match_token(parser, TOKEN_EXISTS)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected EXISTS after IF");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_EXISTS);
        stmt->data.drop_view.if_exists = true;
    }
    
    // Parse view name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected view name");
        return NULL;
    }
    
    stmt->data.drop_view.view_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Check for CASCADE option
    if (parser_match_token(parser, TOKEN_IDENTIFIER) && 
        strcasecmp(parser->current_token->value, "CASCADE") == 0) {
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        stmt->data.drop_view.cascade = true;
    }
    
    return stmt;
}

// DROP INDEX parser
statement_t* parser_parse_drop_index(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_DROP_INDEX;
    
    // Consume DROP token
    if (!parser_consume_token(parser, TOKEN_DROP)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected DROP");
        return NULL;
    }
    
    // Consume INDEX token
    if (!parser_consume_token(parser, TOKEN_INDEX)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected INDEX");
        return NULL;
    }
    
    // Check for IF EXISTS (optional)
    if (parser->current_token && parser->current_token->type == TOKEN_IF) {
        token_destroy(parser->current_token);
        parser->current_token = lexer_next_token(parser->lexer);
        
        if (!parser_consume_token(parser, TOKEN_EXISTS)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected EXISTS after IF");
            return NULL;
        }
        
        stmt->data.drop_index.if_exists = true;
    }
    
    // Parse index name
    if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected index name");
        return NULL;
    }
    
    stmt->data.drop_index.index_name = strdup(parser->current_token->value);
    token_destroy(parser->current_token);
    parser->current_token = lexer_next_token(parser->lexer);
    
    // Optional ON table_name (some SQL dialects require this)
    if (parser->current_token && parser->current_token->type == TOKEN_ON) {
        token_destroy(parser->current_token);
        parser->current_token = lexer_next_token(parser->lexer);
        
        if (!parser->current_token || parser->current_token->type != TOKEN_IDENTIFIER) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected table name after ON");
            return NULL;
        }
        
        stmt->data.drop_index.table_name = strdup(parser->current_token->value);
        token_destroy(parser->current_token);
        parser->current_token = lexer_next_token(parser->lexer);
    }
    
    return stmt;
}

// DROP TABLE parser
statement_t* parser_parse_drop_table(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_DROP_TABLE;
    
    // Consume DROP token
    if (!parser_consume_token(parser, TOKEN_DROP)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected DROP");
        return NULL;
    }
    
    // Consume TABLE token
    if (!parser_consume_token(parser, TOKEN_TABLE)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected TABLE");
        return NULL;
    }
    
    // Check for IF EXISTS option
    if (parser_match_token(parser, TOKEN_IF)) {
        parser_consume_token(parser, TOKEN_IF);
        if (!parser_match_token(parser, TOKEN_EXISTS)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected EXISTS after IF");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_EXISTS);
        stmt->data.drop_table.if_exists = true;
    }
    
    // Parse table name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected table name");
        return NULL;
    }
    
    stmt->data.drop_table.table_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Check for CASCADE option
    if (parser_match_token(parser, TOKEN_IDENTIFIER) && 
        strcasecmp(parser->current_token->value, "CASCADE") == 0) {
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        stmt->data.drop_table.cascade = true;
    }
    
    return stmt;
}

// Parse DROP DATABASE statement: DROP DATABASE [IF EXISTS] database_name
statement_t* parser_parse_drop_database(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_DROP_DATABASE;
    stmt->data.drop_database.if_exists = false;
    
    // Consume DROP token
    if (!parser_consume_token(parser, TOKEN_DROP)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected DROP");
        return NULL;
    }
    
    // Consume DATABASE token
    if (!parser_consume_token(parser, TOKEN_DATABASE)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected DATABASE");
        return NULL;
    }
    
    // Check for IF EXISTS option
    if (parser_match_token(parser, TOKEN_IF)) {
        parser_consume_token(parser, TOKEN_IF);
        if (!parser_consume_token(parser, TOKEN_EXISTS)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected EXISTS after IF");
            return NULL;
        }
        stmt->data.drop_database.if_exists = true;
    }
    
    // Parse database name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected database name");
        return NULL;
    }
    
    stmt->data.drop_database.database_name = strdup(parser->current_token->value);
    if (!stmt->data.drop_database.database_name) {
        statement_destroy(stmt);
        parser_set_error(parser, "Memory allocation failed");
        return NULL;
    }
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    return stmt;
}

// Parse ALTER TABLE statement: ALTER TABLE table_name ADD COLUMN column_name column_type
statement_t* parser_parse_alter_table(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_ALTER_TABLE;
    stmt->line = parser->current_token->line;
    stmt->column = parser->current_token->column;
    
    // Initialize defaults
    stmt->data.alter_table.operation = ALTER_ADD_COLUMN; // Default operation
    stmt->data.alter_table.column_length = 0;
    stmt->data.alter_table.not_null = false;
    stmt->data.alter_table.primary_key = false;
    stmt->data.alter_table.unique = false;
    stmt->data.alter_table.default_value = NULL;
    
    // Consume ALTER token
    if (!parser_consume_token(parser, TOKEN_ALTER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected ALTER");
        return NULL;
    }
    
    // Consume TABLE token
    if (!parser_consume_token(parser, TOKEN_TABLE)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected TABLE");
        return NULL;
    }
    
    // Parse table name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected table name");
        return NULL;
    }
    
    stmt->data.alter_table.table_name = strdup(parser->current_token->value);
    if (!stmt->data.alter_table.table_name) {
        statement_destroy(stmt);
        parser_set_error(parser, "Memory allocation failed");
        return NULL;
    }
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Parse operation type (ADD, DROP, MODIFY)
    if (parser_match_token(parser, TOKEN_DROP)) {
        stmt->data.alter_table.operation = ALTER_DROP_COLUMN;
        parser_consume_token(parser, TOKEN_DROP);
    } else if (parser_match_token(parser, TOKEN_IDENTIFIER)) {
        if (strcasecmp(parser->current_token->value, "ADD") == 0) {
            stmt->data.alter_table.operation = ALTER_ADD_COLUMN;
        } else if (strcasecmp(parser->current_token->value, "MODIFY") == 0) {
            stmt->data.alter_table.operation = ALTER_MODIFY_COLUMN;
        } else {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected ADD, DROP, or MODIFY after table name");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_IDENTIFIER);
    } else {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected operation after table name");
        return NULL;
    }
    
    // Expect COLUMN token (for all operations)
    if (!parser_match_token(parser, TOKEN_IDENTIFIER) ||
        strcasecmp(parser->current_token->value, "COLUMN") != 0) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected COLUMN after operation");
        return NULL;
    }
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Parse column name (allow some keywords as column names)
    if (parser_match_token(parser, TOKEN_IDENTIFIER)) {
        stmt->data.alter_table.column_name = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
    } else if (parser_match_token(parser, TOKEN_STATUS)) {
        stmt->data.alter_table.column_name = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_STATUS);
    } else {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected column name");
        return NULL;
    }
    
    if (!stmt->data.alter_table.column_name) {
        statement_destroy(stmt);
        parser_set_error(parser, "Memory allocation failed");
        return NULL;
    }
    
    // For DROP COLUMN, we're done - no need to parse type
    if (stmt->data.alter_table.operation == ALTER_DROP_COLUMN) {
        return stmt;
    }
    
    // Parse column type (for ADD COLUMN and MODIFY COLUMN)
    switch (parser->current_token->type) {
        case TOKEN_INT:
            stmt->data.alter_table.column_type = DATA_TYPE_INT;
            break;
        case TOKEN_VARCHAR:
            stmt->data.alter_table.column_type = DATA_TYPE_VARCHAR;
            parser_consume_token(parser, TOKEN_VARCHAR);
            
            // Parse length for VARCHAR
            if (parser_match_token(parser, TOKEN_LPAREN)) {
                parser_consume_token(parser, TOKEN_LPAREN);
                if (parser_match_token(parser, TOKEN_NUMBER)) {
                    stmt->data.alter_table.column_length = atoi(parser->current_token->value);
                    parser_consume_token(parser, TOKEN_NUMBER);
                } else {
                    statement_destroy(stmt);
                    parser_set_error(parser, "Expected length after VARCHAR(");
                    return NULL;
                }
                if (!parser_consume_token(parser, TOKEN_RPAREN)) {
                    statement_destroy(stmt);
                    parser_set_error(parser, "Expected )");
                    return NULL;
                }
            }
            goto skip_next_token;
        case TOKEN_CHAR:
            stmt->data.alter_table.column_type = DATA_TYPE_CHAR;
            parser_consume_token(parser, TOKEN_CHAR);
            
            // Parse length for CHAR
            if (parser_match_token(parser, TOKEN_LPAREN)) {
                parser_consume_token(parser, TOKEN_LPAREN);
                if (parser_match_token(parser, TOKEN_NUMBER)) {
                    stmt->data.alter_table.column_length = atoi(parser->current_token->value);
                    parser_consume_token(parser, TOKEN_NUMBER);
                } else {
                    statement_destroy(stmt);
                    parser_set_error(parser, "Expected length after CHAR(");
                    return NULL;
                }
                if (!parser_consume_token(parser, TOKEN_RPAREN)) {
                    statement_destroy(stmt);
                    parser_set_error(parser, "Expected )");
                    return NULL;
                }
            }
            goto skip_next_token;
        case TOKEN_TEXT:
            stmt->data.alter_table.column_type = DATA_TYPE_TEXT;
            break;
        case TOKEN_FLOAT:
            stmt->data.alter_table.column_type = DATA_TYPE_FLOAT;
            break;
        case TOKEN_DOUBLE:
            stmt->data.alter_table.column_type = DATA_TYPE_DOUBLE;
            break;
        default:
            statement_destroy(stmt);
            parser_set_error(parser, "Unsupported column type");
            return NULL;
    }
    parser_consume_token(parser, parser->current_token->type);
    
    skip_next_token:
    
    // Parse optional constraints (NOT NULL, PRIMARY KEY, etc.)
    while (parser->current_token && parser->current_token->type != TOKEN_SEMICOLON && 
           parser->current_token->type != TOKEN_EOF) {
        if (parser_match_token(parser, TOKEN_NOT)) {
            parser_consume_token(parser, TOKEN_NOT);
            if (!parser_consume_token(parser, TOKEN_NULL)) {
                statement_destroy(stmt);
                parser_set_error(parser, "Expected NULL after NOT");
                return NULL;
            }
            stmt->data.alter_table.not_null = true;
        } else if (parser_match_token(parser, TOKEN_PRIMARY)) {
            parser_consume_token(parser, TOKEN_PRIMARY);
            if (!parser_consume_token(parser, TOKEN_KEY)) {
                statement_destroy(stmt);
                parser_set_error(parser, "Expected KEY after PRIMARY");
                return NULL;
            }
            stmt->data.alter_table.primary_key = true;
        } else if (parser_match_token(parser, TOKEN_UNIQUE)) {
            parser_consume_token(parser, TOKEN_UNIQUE);
            stmt->data.alter_table.unique = true;
        } else if (parser_match_token(parser, TOKEN_DEFAULT)) {
            parser_consume_token(parser, TOKEN_DEFAULT);
            if (parser_match_token(parser, TOKEN_STRING) || parser_match_token(parser, TOKEN_NUMBER)) {
                stmt->data.alter_table.default_value = strdup(parser->current_token->value);
                parser_consume_token(parser, parser->current_token->type);
            } else {
                statement_destroy(stmt);
                parser_set_error(parser, "Expected value after DEFAULT");
                return NULL;
            }
        } else {
            break; // No more recognized constraints
        }
    }
    
    return stmt;
}

// Parse USE statement: USE database_name
statement_t* parser_parse_use(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_USE;
    stmt->line = parser->current_token->line;
    stmt->column = parser->current_token->column;
    
    // Consume USE token
    parser_consume_token(parser, TOKEN_USE);
    
    // Parse database name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected database name after USE");
        return NULL;
    }
    
    stmt->data.use.database_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    return stmt;
}

// Parse DESCRIBE statement: DESCRIBE table_name
statement_t* parser_parse_describe(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_DESCRIBE;
    stmt->line = parser->current_token->line;
    stmt->column = parser->current_token->column;
    
    // Consume DESCRIBE token
    parser_consume_token(parser, TOKEN_DESCRIBE);
    
    // Parse table name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected table name after DESCRIBE");
        return NULL;
    }
    
    stmt->data.describe.table_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    return stmt;
}

// Parse SHOW statements: SHOW DATABASES, SHOW TABLES, SHOW COLUMNS FROM table, SHOW CREATE TABLE table, SHOW STATUS
statement_t* parser_parse_show(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->line = parser->current_token->line;
    stmt->column = parser->current_token->column;
    
    // Consume SHOW token
    parser_consume_token(parser, TOKEN_SHOW);
    
    // Determine what to show
    if (!parser->current_token) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected keyword after SHOW");
        return NULL;
    }
    
    if (parser_match_token(parser, TOKEN_IDENTIFIER)) {
        if (strcasecmp(parser->current_token->value, "DATABASES") == 0) {
            stmt->type = STMT_SHOW_DATABASES;
            parser_consume_token(parser, TOKEN_IDENTIFIER);
        } else if (strcasecmp(parser->current_token->value, "TABLES") == 0) {
            stmt->type = STMT_SHOW_TABLES;
            parser_consume_token(parser, TOKEN_IDENTIFIER);
        } else {
            statement_destroy(stmt);
            parser_set_error(parser, "Unknown SHOW command");
            return NULL;
        }
    } else if (parser_match_token(parser, TOKEN_COLUMNS)) {
        stmt->type = STMT_SHOW_COLUMNS;
        parser_consume_token(parser, TOKEN_COLUMNS);
        
        // Expect FROM keyword
        if (!parser_match_token(parser, TOKEN_FROM)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected FROM after SHOW COLUMNS");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_FROM);
        
        // Parse table name
        if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected table name after SHOW COLUMNS FROM");
            return NULL;
        }
        
        stmt->data.show.table_name = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        
    } else if (parser_match_token(parser, TOKEN_STATUS)) {
        stmt->type = STMT_SHOW_STATUS;
        parser_consume_token(parser, TOKEN_STATUS);
        
    } else if (parser_match_token(parser, TOKEN_CREATE)) {
        parser_consume_token(parser, TOKEN_CREATE);
        
        if (!parser_match_token(parser, TOKEN_TABLE)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected TABLE after SHOW CREATE");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_TABLE);
        
        if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected table name after SHOW CREATE TABLE");
            return NULL;
        }
        
        stmt->type = STMT_SHOW_CREATE_TABLE;
        stmt->data.show.table_name = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        
    } else {
        statement_destroy(stmt);
        parser_set_error(parser, "Unknown SHOW command");
        return NULL;
    }
    
    return stmt;
}

// CREATE TRIGGER parser
statement_t* parser_parse_create_trigger(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_CREATE_TRIGGER;
    
    // Consume CREATE token
    if (!parser_consume_token(parser, TOKEN_CREATE)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected CREATE");
        return NULL;
    }
    
    // Check for OR REPLACE option
    if (parser_match_token(parser, TOKEN_OR)) {
        parser_consume_token(parser, TOKEN_OR);
        if (!parser_match_token(parser, TOKEN_IDENTIFIER) || 
            strcasecmp(parser->current_token->value, "REPLACE") != 0) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected REPLACE after OR");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        stmt->data.create_trigger.or_replace = true;
    }
    
    // Consume TRIGGER token
    if (!parser_consume_token(parser, TOKEN_TRIGGER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected TRIGGER");
        return NULL;
    }
    
    // Parse trigger name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected trigger name");
        return NULL;
    }
    
    stmt->data.create_trigger.trigger_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Parse timing: BEFORE, AFTER, or INSTEAD OF
    uint8_t timing = 0;
    if (parser_match_token(parser, TOKEN_BEFORE)) {
        timing = 0; // TRIGGER_TIMING_BEFORE
        parser_consume_token(parser, TOKEN_BEFORE);
    } else if (parser_match_token(parser, TOKEN_AFTER)) {
        timing = 1; // TRIGGER_TIMING_AFTER
        parser_consume_token(parser, TOKEN_AFTER);
    } else if (parser_match_token(parser, TOKEN_INSTEAD)) {
        timing = 2; // TRIGGER_TIMING_INSTEAD_OF
        parser_consume_token(parser, TOKEN_INSTEAD);
        if (!parser_match_token(parser, TOKEN_IDENTIFIER) ||
            strcasecmp(parser->current_token->value, "OF") != 0) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected OF after INSTEAD");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_IDENTIFIER);
    } else {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected BEFORE, AFTER, or INSTEAD OF");
        return NULL;
    }
    stmt->data.create_trigger.timing = timing;
    
    // Parse events: INSERT, UPDATE, DELETE (can be multiple)
    uint8_t events = 0;
    bool first_event = true;
    
    do {
        if (!first_event) {
            if (!parser_match_token(parser, TOKEN_OR)) {
                break;
            }
            parser_consume_token(parser, TOKEN_OR);
        }
        
        if (parser_match_token(parser, TOKEN_INSERT)) {
            events |= 0x01; // TRIGGER_EVENT_INSERT
            parser_consume_token(parser, TOKEN_INSERT);
        } else if (parser_match_token(parser, TOKEN_UPDATE)) {
            events |= 0x02; // TRIGGER_EVENT_UPDATE
            parser_consume_token(parser, TOKEN_UPDATE);
        } else if (parser_match_token(parser, TOKEN_DELETE)) {
            events |= 0x04; // TRIGGER_EVENT_DELETE
            parser_consume_token(parser, TOKEN_DELETE);
        } else if (first_event) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected INSERT, UPDATE, or DELETE");
            return NULL;
        } else {
            break;
        }
        
        first_event = false;
    } while (true);
    
    stmt->data.create_trigger.events = events;
    
    // Parse ON table_name
    if (!parser_match_token(parser, TOKEN_ON)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected ON after trigger events");
        return NULL;
    }
    parser_consume_token(parser, TOKEN_ON);
    
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected table name after ON");
        return NULL;
    }
    
    stmt->data.create_trigger.table_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Optional FOR EACH ROW (default is FOR EACH ROW)
    stmt->data.create_trigger.for_each_row = true;
    if (parser_match_token(parser, TOKEN_FOR)) {
        parser_consume_token(parser, TOKEN_FOR);
        if (!parser_match_token(parser, TOKEN_EACH)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected EACH after FOR");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_EACH);
        
        if (parser_match_token(parser, TOKEN_ROW)) {
            parser_consume_token(parser, TOKEN_ROW);
            stmt->data.create_trigger.for_each_row = true;
        } else if (parser_match_token(parser, TOKEN_IDENTIFIER) &&
                   strcasecmp(parser->current_token->value, "STATEMENT") == 0) {
            parser_consume_token(parser, TOKEN_IDENTIFIER);
            stmt->data.create_trigger.for_each_row = false;
        } else {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected ROW or STATEMENT after FOR EACH");
            return NULL;
        }
    }
    
    // Optional WHEN condition
    if (parser_match_token(parser, TOKEN_WHEN)) {
        parser_consume_token(parser, TOKEN_WHEN);
        
        // Parse condition expression - simplified: read until BEGIN
        // In a full implementation, we would parse the expression properly
        char condition_buffer[1024] = {0};
        size_t pos = 0;
        
        while (parser->current_token && 
               parser->current_token->type != TOKEN_EOF &&
               !(parser_match_token(parser, TOKEN_IDENTIFIER) && 
                 strcasecmp(parser->current_token->value, "BEGIN") == 0) &&
               pos < sizeof(condition_buffer) - 1) {
            
            strncpy(condition_buffer + pos, parser->current_token->value, 
                    sizeof(condition_buffer) - pos - 1);
            pos += strlen(parser->current_token->value);
            if (pos < sizeof(condition_buffer) - 1) {
                condition_buffer[pos++] = ' ';
            }
            
            token_destroy(parser->current_token);
            parser->current_token = lexer_next_token(parser->lexer);
        }
        
        if (pos > 0) {
            condition_buffer[pos - 1] = '\0'; // Remove trailing space
            stmt->data.create_trigger.condition = strdup(condition_buffer);
        }
    }
    
    // Parse BEGIN ... END block or single SQL statement
    if (parser_match_token(parser, TOKEN_IDENTIFIER) && 
        strcasecmp(parser->current_token->value, "BEGIN") == 0) {
        parser_consume_token(parser, TOKEN_IDENTIFIER);
        
        // Parse SQL statements until END
        char action_buffer[4096] = {0};
        size_t pos = 0;
        
        while (parser->current_token && 
               parser->current_token->type != TOKEN_EOF &&
               !(parser_match_token(parser, TOKEN_IDENTIFIER) && 
                 strcasecmp(parser->current_token->value, "END") == 0) &&
               pos < sizeof(action_buffer) - 1) {
            
            strncpy(action_buffer + pos, parser->current_token->value, 
                    sizeof(action_buffer) - pos - 1);
            pos += strlen(parser->current_token->value);
            if (pos < sizeof(action_buffer) - 1) {
                action_buffer[pos++] = ' ';
            }
            
            token_destroy(parser->current_token);
            parser->current_token = lexer_next_token(parser->lexer);
        }
        
        if (parser_match_token(parser, TOKEN_IDENTIFIER) && 
            strcasecmp(parser->current_token->value, "END") == 0) {
            parser_consume_token(parser, TOKEN_IDENTIFIER);
        } else {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected END to close trigger body");
            return NULL;
        }
        
        if (pos > 0) {
            action_buffer[pos - 1] = '\0'; // Remove trailing space
            stmt->data.create_trigger.action_sql = strdup(action_buffer);
        }
    } else {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected BEGIN for trigger body");
        return NULL;
    }
    
    return stmt;
}

// DROP TRIGGER parser
statement_t* parser_parse_drop_trigger(parser_t* parser) {
    statement_t* stmt = calloc(1, sizeof(statement_t));
    if (!stmt) {
        parser_set_error(parser, "Out of memory");
        return NULL;
    }
    
    stmt->type = STMT_DROP_TRIGGER;
    
    // Consume DROP token
    if (!parser_consume_token(parser, TOKEN_DROP)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected DROP");
        return NULL;
    }
    
    // Consume TRIGGER token
    if (!parser_consume_token(parser, TOKEN_TRIGGER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected TRIGGER");
        return NULL;
    }
    
    // Check for IF EXISTS option
    if (parser_match_token(parser, TOKEN_IF)) {
        parser_consume_token(parser, TOKEN_IF);
        if (!parser_match_token(parser, TOKEN_EXISTS)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected EXISTS after IF");
            return NULL;
        }
        parser_consume_token(parser, TOKEN_EXISTS);
        stmt->data.drop_trigger.if_exists = true;
    }
    
    // Parse trigger name
    if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
        statement_destroy(stmt);
        parser_set_error(parser, "Expected trigger name");
        return NULL;
    }
    
    stmt->data.drop_trigger.trigger_name = strdup(parser->current_token->value);
    parser_consume_token(parser, TOKEN_IDENTIFIER);
    
    // Optional ON table_name (some databases require this)
    if (parser_match_token(parser, TOKEN_ON)) {
        parser_consume_token(parser, TOKEN_ON);
        if (!parser_match_token(parser, TOKEN_IDENTIFIER)) {
            statement_destroy(stmt);
            parser_set_error(parser, "Expected table name after ON");
            return NULL;
        }
        
        stmt->data.drop_trigger.table_name = strdup(parser->current_token->value);
        parser_consume_token(parser, TOKEN_IDENTIFIER);
    }
    
    return stmt;
}

// Convert data_type_t enum to string representation
const char* data_type_to_string(data_type_t type) {
    switch (type) {
        case DATA_TYPE_TINYINT:
            return "TINYINT";
        case DATA_TYPE_INT:
            return "INT";
        case DATA_TYPE_BIGINT:
            return "BIGINT";
        case DATA_TYPE_FLOAT:
            return "FLOAT";
        case DATA_TYPE_DOUBLE:
            return "DOUBLE";
        case DATA_TYPE_CHAR:
            return "CHAR";
        case DATA_TYPE_VARCHAR:
            return "VARCHAR";
        case DATA_TYPE_TEXT:
            return "TEXT";
        case DATA_TYPE_JSON:
            return "JSON";
        case DATA_TYPE_DATE:
            return "DATE";
        case DATA_TYPE_DATETIME:
            return "DATETIME";
        case DATA_TYPE_TIMESTAMP:
            return "TIMESTAMP";
        case DATA_TYPE_INVALID:
        default:
            return "UNKNOWN";
    }
}

// Helper function to check if a column reference exists in table references
static bool column_exists_in_tables(const char* column_name, table_ref_t* tables) {
    if (!column_name || !tables) {
        return false;
    }
    
    // Simple implementation: for now, we assume any column reference without a table qualifier
    // that appears in a subquery might be correlated. A more sophisticated implementation would
    // need access to schema information to determine actual column existence.
    
    table_ref_t* current = tables;
    while (current) {
        // If column name contains a table qualifier that matches a subquery table, it's not correlated
        if (current->table_name && strstr(column_name, current->table_name)) {
            return true;
        }
        if (current->alias && strstr(column_name, current->alias)) {
            return true;
        }
        current = current->next;
    }
    
    return false;
}

// Helper function to extract column references from expressions
static void extract_column_references(expression_t* expr, char*** refs, uint32_t* count, 
                                     table_ref_t* subquery_tables) {
    if (!expr || !refs || !count) {
        return;
    }
    
    switch (expr->type) {
        case EXPR_COLUMN:
            if (expr->data.column.column_name) {
                // Build full column reference (table.column or just column)
                char* full_ref = NULL;
                if (expr->data.column.table_name) {
                    size_t len = strlen(expr->data.column.table_name) + strlen(expr->data.column.column_name) + 2;
                    full_ref = malloc(len);
                    if (full_ref) {
                        snprintf(full_ref, len, "%s.%s", expr->data.column.table_name, expr->data.column.column_name);
                    }
                } else {
                    full_ref = strdup(expr->data.column.column_name);
                }
                
                if (full_ref) {
                    // Check if this column exists in the subquery's own tables
                    if (!column_exists_in_tables(full_ref, subquery_tables)) {
                        // This might be a correlated reference - add it to the list
                        *refs = realloc(*refs, (*count + 1) * sizeof(char*));
                        if (*refs) {
                            (*refs)[*count] = full_ref;
                            (*count)++;
                        } else {
                            free(full_ref);
                        }
                    } else {
                        free(full_ref);
                    }
                }
            }
            break;
            
        case EXPR_BINARY_OP:
            extract_column_references(expr->data.binary_op.left, refs, count, subquery_tables);
            extract_column_references(expr->data.binary_op.right, refs, count, subquery_tables);
            break;
            
        case EXPR_UNARY_OP:
            extract_column_references(expr->data.unary_op.operand, refs, count, subquery_tables);
            break;
            
        case EXPR_FUNCTION_CALL:
            for (uint32_t i = 0; i < expr->data.function_call.arg_count; i++) {
                extract_column_references(expr->data.function_call.args[i], refs, count, subquery_tables);
            }
            break;
            
        case EXPR_LIST:
            for (uint32_t i = 0; i < expr->data.list.count; i++) {
                extract_column_references(expr->data.list.expressions[i], refs, count, subquery_tables);
            }
            break;
            
        case EXPR_SUBQUERY:
            // Nested subqueries - for now, we don't handle deep nesting
            break;
            
        default:
            // EXPR_LITERAL, EXPR_STAR, etc. - no column references
            break;
    }
}

// Main correlation detection function
static void detect_subquery_correlation(expression_t* subquery_expr, statement_t* subquery_stmt) {
    if (!subquery_expr || !subquery_stmt || subquery_stmt->type != STMT_SELECT) {
        // Initialize as non-correlated
        subquery_expr->data.subquery.is_correlated = false;
        subquery_expr->data.subquery.correlation_refs = NULL;
        subquery_expr->data.subquery.correlation_count = 0;
        return;
    }
    
    // Initialize correlation tracking
    char** correlation_refs = NULL;
    uint32_t correlation_count = 0;
    
    // Get the subquery's table references to know what tables are available in the subquery
    table_ref_t* subquery_tables = subquery_stmt->data.select.from_list;
    
    // Analyze different parts of the SELECT statement for column references
    
    // 1. Check SELECT list
    if (subquery_stmt->data.select.select_list) {
        extract_column_references(subquery_stmt->data.select.select_list, 
                                &correlation_refs, &correlation_count, subquery_tables);
    }
    
    // 2. Check WHERE clause
    if (subquery_stmt->data.select.where_clause) {
        extract_column_references(subquery_stmt->data.select.where_clause, 
                                &correlation_refs, &correlation_count, subquery_tables);
    }
    
    // 3. Check GROUP BY clause
    if (subquery_stmt->data.select.group_by) {
        extract_column_references(subquery_stmt->data.select.group_by, 
                                &correlation_refs, &correlation_count, subquery_tables);
    }
    
    // 4. Check HAVING clause
    if (subquery_stmt->data.select.having) {
        extract_column_references(subquery_stmt->data.select.having, 
                                &correlation_refs, &correlation_count, subquery_tables);
    }
    
    // 5. Check ORDER BY clause
    if (subquery_stmt->data.select.order_by) {
        order_by_item_t* order_item = subquery_stmt->data.select.order_by;
        while (order_item) {
            if (order_item->expression) {
                extract_column_references(order_item->expression, 
                                        &correlation_refs, &correlation_count, subquery_tables);
            }
            order_item = order_item->next;
        }
    }
    
    // Set correlation information
    subquery_expr->data.subquery.is_correlated = (correlation_count > 0);
    subquery_expr->data.subquery.correlation_refs = correlation_refs;
    subquery_expr->data.subquery.correlation_count = correlation_count;
}

// Parse ORDER BY list with ASC/DESC modifiers
order_by_item_t* parser_parse_order_by_list(parser_t* parser) {
    if (!parser) return NULL;
    
    order_by_item_t* first_item = NULL;
    order_by_item_t* current_item = NULL;
    
    do {
        // Create new ORDER BY item
        order_by_item_t* item = calloc(1, sizeof(order_by_item_t));
        if (!item) {
            parser_set_error(parser, "Out of memory");
            order_by_item_destroy(first_item);
            return NULL;
        }
        
        // Parse the expression
        item->expression = parser_parse_expression(parser);
        if (!item->expression) {
            free(item);
            order_by_item_destroy(first_item);
            return NULL;
        }
        
        // Default to ASC if no modifier specified
        item->direction = SORT_ASC;
        
        // Check for ASC/DESC modifier
        if (parser_match_token(parser, TOKEN_ASC)) {
            item->direction = SORT_ASC;
            parser_consume_token(parser, TOKEN_ASC);
        } else if (parser_match_token(parser, TOKEN_DESC)) {
            item->direction = SORT_DESC;
            parser_consume_token(parser, TOKEN_DESC);
        }
        
        // Link to the list
        if (!first_item) {
            first_item = item;
            current_item = item;
        } else {
            current_item->next = item;
            current_item = item;
        }
        
        // Check for comma to continue parsing more items
        if (parser_match_token(parser, TOKEN_COMMA)) {
            if (!parser_consume_token(parser, TOKEN_COMMA)) {
                order_by_item_destroy(first_item);
                return NULL;
            }
        } else {
            break; // No more items
        }
        
    } while (true);
    
    return first_item;
}

// Memory management for ORDER BY items
void order_by_item_destroy(order_by_item_t* item) {
    while (item) {
        order_by_item_t* next = item->next;
        
        if (item->expression) {
            expression_destroy(item->expression);
        }
        
        free(item);
        item = next;
    }
}